简体   繁体   中英

fork/exec: stderr/stdout lost

I wrote a programm which starts a new process group and then forks.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char** argv) {
    if(0 != setpgid(0,0)) {
        fprintf(stderr, "Process group creation failed.");
    }
    pid_t pid = fork();
    if(-1 == pid) {
        // ups, error
        fprintf(stderr, "Fork failed!\n");
        return 1;
    } else if(0==pid) {
        // this is the child process
        char **partial = malloc((argc-1)*sizeof(char*));
        for(int i=1;i<argc;i++) {
            partial[i-1] = argv[i];
        }
        execvp(partial[0], partial);
        exit(127);
    }
    // this is the parent process
    int status;
    waitpid(pid, &status, 0);
    return status;
}

If I call it with

./pgroup echo Test

it works as expected.

If I call it with

./pgroup bash -c "echo Test"

No output is written to my terminal. Why is that?

The execve call is causing a segfault:

==22934== Command: ./testt bash -c echo\ Test
==22934== 
==22935== Syscall param execve(argv) points to unaddressable byte(s)
==22935==    at 0x4EF9537: execve (in /usr/lib64/libc-2.20.so)
==22935==    by 0x4EF9D35: execvpe (in /usr/lib64/libc-2.20.so)
==22935==    by 0x400822: main (testt.c:23)
==22935==  Address 0x51f2058 is 0 bytes after a block of size 24 alloc'd
==22935==    at 0x4C29BCF: malloc (in /usr/lib64/valgrind /vgpreload_memcheck-amd64-linux.so)
==22935==    by 0x4007C5: main (testt.c:18)
==22935== 

In particular, don't mess with argv[0] (you don't here, but just sayin). And - this is the key here - you've got to strcpy() the other args into heap space, not just pass existing pointers. You didn't allocate that argv, so don't expect it to "stick around" when the startup routine runs again, etc... Lastly, you need to copy a NULL to the and of the argument list.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

Do not mix headers like that. sys/ headers go first.

int main(int argc, char** argv) {
    if(0 != setpgid(0,0)) {
        fprintf(stderr, "Process group creation failed.");
    }

Yoda-style comparisons look terrible and have no merit.

    pid_t pid = fork();
    if(-1 == pid) {
        // ups, error
        fprintf(stderr, "Fork failed!\n");
        return 1;
    } else if(0==pid) {
        // this is the child process
        char **partial = malloc((argc-1)*sizeof(char*));
        for(int i=1;i<argc;i++) {
            partial[i-1] = argv[i];
        }

What's the point of this exercise? How about argv++ and then you can use it directly in execvp. Your loop is atrocious and unnecessary. You malloc argc - 1, but loop condition is i < argc which is incosistent, which is made up for by another weirdness of i not starting from 0. Error inducing style.

Also you did not validate any arguments.

        execvp(partial[0], partial);

If you checked the error you would see that fails. The simplest "first contact" tool is strace, it would have told you exactly what's up, see:

[pid 15735] execve("/usr/bin/bash", ["bash", "-c", "echo test", 0x20fe1], [/* 58 vars */]) = -1 EFAULT (Bad address)

From this it is obvious that arg array is not properly terminated and the kernel tried to copy in some garbage.

So, your 'echo test' example worked by pure accident as it happened to have a zero in there.

If you had debugging enabled in your malloc it would have failed for that case as well.

        exit(127);

That's not how you exit in a child which did not execve. See _Exit.

    }
    // this is the parent process
    int status;
    waitpid(pid, &status, 0);
    return status;

This value is not suitable for retutning. See relevant macros in waitpid manpage. The shell supports values from 0 to 255. This returns 32512 which is divisible by 256 and thus ends up being 0.

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM