2

I know this question has been asked a billion times, but all the solutions are not working for me. I need to stream the stdout of an execvp via a socket to a client. The relevant client code is this

static void execute_cmd(int fd, char *cmd, char **params) {
    pid_t cid;
    size_t i = 0, c = 0;

    cid = fork();

    if(cid == 0) {
        close(STDOUT_FILENO);
        dup2(fd, STDOUT_FILENO);

        if(execvp(cmd, params) < 0) {
            fprintf(stderr, "Could not execute \"%s\": %d\n", cmd, errno);
            exit(1);
        }
    } else {
        close(fd);
        waitpid(cid, NULL, 0);
        exit(1);
    }
}

I have tried to copy the answer on this question. However, I get nothing back when I try this code:

int sockfd = serverConnect();
write(sockfd, "echo math", 11);
n = read(sockfd, buffer, 1023);

printf("Got %d bytes\n", n);
printf("%s\n", buffer);

close(sockfd);

I triple checked that the connection is established correctly. When I replace execute_cmd with a simple write, the client correctly prints the answer. But nothing happens when I execute the code above, I get no bytes back. I have removed the dup2 call and got no output from the execvp call either.

Getting quite desperate here, tried pipe and whatever I could find. Where did I go wrong? The command itself is ok, too, works on the shell, and the execvp call does not throw an error.

Community
  • 1
  • 1
Lanbo
  • 15,118
  • 16
  • 70
  • 147
  • You don't have CLOEXEC set on the fd? – harmic Jun 03 '14 at 11:56
  • Note: You're fortunate (actually, *not-so-fortunate*) that `write(sockfd, "echo math", 11);` doesn't crash your process with an access violation. You're reading 11 `char` of data from a memory region only guaranteed to be *10* `char` long (9+1). – WhozCraig Jun 03 '14 at 11:57
  • @harmic Uh, not voluntarily. I have no code that would set that, is it set implicitely? – Lanbo Jun 03 '14 at 11:58
  • @WhozCraig I just corrected that before you wrote it, but that has no influence on the problem. – Lanbo Jun 03 '14 at 11:59
  • It is not set implicitly. It would be set using option O_CLOEXEC to open, or SOCK_CLOEXEC to socket or accept, or after opening via fcntl and FD_CLOEXEC. – harmic Jun 03 '14 at 12:08
  • @harmic Does that mean I *have* to set it or that it should not be set? – Lanbo Jun 03 '14 at 12:09
  • You should not set it. In any case I was just reading the man page for dup2 and it says 'The two descriptors do not share file descriptor flags (the close-on-exec flag). The close-on-exec flag (FD_CLOEXEC; see fcntl(2)) for the duplicate descriptor is off.' So it should not matter either way. – harmic Jun 03 '14 at 12:20
  • When it is set, the corresponding for descriptor would be closed automatically on calling any of the exec functions. – harmic Jun 03 '14 at 12:22

1 Answers1

0

Turns out the code above is correct. The problem was an incorrect use of an earlier strtok that resulted in a silent crash of strdup. The fork above was simply never executed, and all my tests were above the strtok line. Only after putting printfs into every line of the code I could find the problem.

Frankly, I feel stupid.

Lanbo
  • 15,118
  • 16
  • 70
  • 147