阅读手册页和几个stackoverflow/stackexchange页面,我正在处理posix_spawn和管道。然而,我遇到了一个问题。下面的代码,三个管道,(stdin,stdout,stderr)看起来工作正常。问题是rv = write(stdin_pipe[PIPE_TO]...
返回一个错误-“没有这样的文件或目录”。奇怪的是这段代码工作正常(没有错误)如果在codelite(一个ide)运行。我不知道这段代码是好还是坏。它会导致内存泄漏或一些灾难。
我很欣赏任何建议。我的意图是,这段代码是抛出一些字符串到grep 1
,然后捕获标准输出。
#include <spawn.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
#define PIPE_TO 1
#define PIPE_FROM 0
int main(int argc, char** argv, char** envv){
int exit_code;
int stdout_pipe[2], stderr_pipe[2], stdin_pipe[2];
posix_spawn_file_actions_t *action, act;
char *args[4];
char *argsmem[] = {"sh", "-c"};
int rv;
char inbuf[] = "1\na\n3\nb\n5\n6\n7\n8\n9\n10\n11\n12\n\0";
char cmd[] = "grep 1";
action = &act;
if(pipe(stdout_pipe) || pipe(stderr_pipe) || pipe(stdin_pipe))
printf("pipe returned an error.\n");
posix_spawn_file_actions_init(action);
posix_spawn_file_actions_addclose(action, stdout_pipe[PIPE_FROM]);
posix_spawn_file_actions_addclose(action, stderr_pipe[PIPE_FROM]);
posix_spawn_file_actions_addclose(action, stdin_pipe[PIPE_TO]);
posix_spawn_file_actions_adddup2(action, stdout_pipe[PIPE_TO], STDOUT_FILENO);
posix_spawn_file_actions_adddup2(action, stderr_pipe[PIPE_TO], STDERR_FILENO);
posix_spawn_file_actions_adddup2(action, stdin_pipe[PIPE_FROM], STDIN_FILENO);
posix_spawn_file_actions_addclose(action, stdout_pipe[PIPE_TO]);
posix_spawn_file_actions_addclose(action, stderr_pipe[PIPE_TO]);
posix_spawn_file_actions_addclose(action, stdin_pipe[PIPE_FROM]);
args[0] = argsmem[0];
args[1] = argsmem[1];
args[2] = cmd;
args[3] = NULL;
pid_t pid;
if(posix_spawnp(&pid, args[0], action, NULL, args, NULL))
printf("posix_spawnp failed with error: %s\n", strerror(errno));
rv = write(stdin_pipe[PIPE_TO], inbuf, strlen(inbuf));
printf("rv = %d, errno = %d %s\n", rv, errno, strerror(errno));
close(stdin_pipe[PIPE_TO]);
close(stdout_pipe[PIPE_TO]);
close(stderr_pipe[PIPE_TO]);
close(stdin_pipe[PIPE_FROM]);
char buffer[1001];
struct pollfd plist[2];
int rval, bytes_read;
int i;
plist[0].fd = stdout_pipe[PIPE_FROM];
plist[0].events = POLLIN;
plist[1].fd = stderr_pipe[PIPE_FROM];
plist[1].events = POLLIN;
while(rval = poll(plist, 2, -1)){
if(plist[0].revents & POLLIN){
i = 0;
while(bytes_read = read(stdout_pipe[PIPE_FROM], buffer, 1000)){
i += bytes_read;
buffer[bytes_read] = '\0';
printf("%s", buffer);
}
printf("\nread %d bytes from stdout.\n", i);
}
else if(plist[1].revents & POLLIN){
i = 0;
while(bytes_read = read(stderr_pipe[PIPE_FROM], buffer, 1000)){
i += bytes_read;
buffer[bytes_read] = '\0';
printf("%s", buffer);
}
printf("\nread %d bytes from stderr.\n", i);
}
else break;
}
waitpid(pid, &exit_code, 0);
printf("exit code: %d\n", exit_code);
posix_spawn_file_actions_destroy(action);
}
字符串
我的系统是Linux,Debian amd 64测试。摆弄inbuf和cmd,看起来stdout和stderr都不错。
我已经尝试了几个设置(所有debian amd 64测试),没有解决方案。我不想期待任何未来的灾难。
1条答案
按热度按时间piwo6bdm1#
字符串
测试
errno
只有在系统调用失败时才有意义,也就是rv == -1
。还要注意,成功的系统调用 * 不会 * 将errno
重置为0,因此ENOENT
(“没有这样的文件或目录”)是以前错误的遗留结果(顺便说一句,write
不可能返回ENOENT
)。在这个例子中,罪魁祸首是
posix_spawnp
。当然,它没有失败,但是在不同的目录中查找sh
时,它有一些失败的调用。我不熟悉codelite,但是很可能它的PATH
是不同的,并且sh
在第一个目录中找到。