-1

Below program neither load the program to child process nor prints "before" and "after". However ps aux shows the creation of processes (but without loading args0 program). I am using PIPE defined as socketpair. args0[] holds executable name for the child program, args1[] holds the name of the child program. args2 and args3 are predefined values that doesn't change and should be sent to the children as arguments. you can assume char args2[] = "10" --> user input (digit) and converted to string. I just do not understand why at least printf("before") is not printed. i read about fflush and putting \n at every printf, and i did. so everything in my program is printed correctly up to this point.

I would truly appreciate your responses.

char args2[];
char args3[];
//creating pipe
int forkk(pipes *myPipe, server_message *m, char args0[],char args1[]) {
pid_t cpid;

//pipe passed myPipe[i]
if (PIPE(myPipe->fd) == -1) {
    perror("pipe error\n");
    return -1;
}
 fork();
 cpid=getpid();
if (cpid == -1) {
    perror("fork error\n");
    return -1;
}
if (cpid) {
    close(myPipe->fd[1]);
    return 1;//closing one end of parent

} else {

    for (int i = 3; i <= myPipe->fd[0]; i++) {
        close(i);
    }

    dup2(myPipe->fd[1], 0); //redirecting stdin of child
    dup2(myPipe->fd[1], 1); //redirecting stdout of child
    close(myPipe->fd[1]);
    myPipe->cpid = cpid;
    char *newargs[3];
    newargs[0]=args1;
    newargs[1]=args2;
    newargs[2]=args3;
    printf("before\n");
    //fflush(stdout);
    execv(args0,newargs);
    printf("after execv\n");
    write(myPipe->fd[0], &m, sizeof(server_message));  //send the server_msg immediately (pass an array or msg)

}
    return 2;

}

void main(){
....
scanf("%d %d", &width, &height);
sprintf(args2,"%d",height); //converting into to string
sprintf(args3,"%d",width);
char *args0 = "./prey";
char *args1 = "prey";
int r= forkk(&myPipes[2], &msg, args0,args1);

}

I cannot post the entire code as it is long and need explanation. I am most probably having a problem with pointer assignment that i wrongly think is the correct way. Thanks a lot for any kind of help

joy_jlee
  • 103
  • 2
  • 13
  • Compile with all warnings and debug info: `gcc -Wall -Wextra -g` with [GCC](http://gcc.gnu.org/). Improve the code to get no warnings. [use the `gdb` debugger](https://sourceware.org/gdb/onlinedocs/gdb/). Use also [strace(1)](http://man7.org/linux/man-pages/man1/strace.1.html). Don't forget to call `fflush` (probably `fflush(NULL);` ....) at appropriate places (probably before `fork`) – Basile Starynkevitch Mar 16 '18 at 17:41
  • Read documentation of [execv(3)](http://man7.org/linux/man-pages/man3/execv.3.html); it usually does not return (except on failure) – Basile Starynkevitch Mar 16 '18 at 17:44
  • I have no warnings. This is not a complete code so you might have. and you think i didnt read anything before posting. i was debugging with gdb for 5 hrs already. i read exec family group functions multiple times and i am passing correct arguments for execv , however there is smth i don't see and know and that is why i am posting here. – joy_jlee Mar 16 '18 at 17:57
  • Did you use `strace`? It should help. And you are expected to provide some [MCVE] in your question – Basile Starynkevitch Mar 16 '18 at 17:58
  • some part of the program has no critical effect on forking and i think what i provided should be enough for the professional one to see the mistake (&msg and &myPipes also not directly affect the fork). I havent used strace, will use. program forks and never goes to the else part which is the problem itself – joy_jlee Mar 16 '18 at 18:09
  • Next time, don't comment your question. But improve it by editing it much more – Basile Starynkevitch Mar 16 '18 at 18:22
  • it was just another paraphrased version of the header statement. – joy_jlee Mar 17 '18 at 10:21
  • Still it is better to edit your question than to comment it. BTW, if my answer fits, please accept and/or upvote it – Basile Starynkevitch Mar 17 '18 at 10:42

1 Answers1

0

(spoiler: your else branch in your poorly named forkk is never taken!)

Read carefully documentation of execv(3). You should provide a NULL terminated array.

The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a null pointer.

So you should at least code:

char *newargs[4];
newargs[0]=args1;
newargs[1]=args2;
newargs[2]=args3;
newargs[3] = NULL; // mandatory last NULL pointer
execv(args0,newargs);

BTW, the first argument should generally be the program name. So you really want:

char *newargs[5];
newargs[0] = args0;
newargs[1]=args1;
newargs[2]=args2;
newargs[3]=args3;
newargs[4] = NULL; // mandatory last NULL pointer
execv(args0,newargs);

And the documentation also says

The exec() functions return only if an error has occurred.

So in most cases, there is no point to continue here since execv won't return if successful. However, you need to catch the failure. I recommend after your execv

perror(arg0); // or perhaps perror("execv");
exit(EXIT_FAILURE);

Your write(myPipe->fd[0], &m, sizeof(server_message)); smells very bad. I see no point in doing that (only) when execv fails

BTW with strace(1) you would probably have caught such an error (missing terminating NULL pointer for execv).

At last, you always should keep the result of fork(2). See this. So replace:

 fork(); // WRONG
 cpid=getpid(); // always positive!

with cpid = fork();

Of course, you need to handle the three cases: cpid== -1 (which you forgot to handle!), cpid== 0, cpid> 0.

Again, read carefully getpid(2):

getpid() returns the process ID (PID) of the calling process.

and (about getpid & getppid):

These functions are always successful

So getpid never returns 0 (and that is why your else branch in your forkk poorly named function, containing the execvp, never runs). See also credentials(7).

Your void main() is also wrong. main should return an int. You generally define it as int main(int argc, char**argv) ...

PS. Take the habit of reading carefully the documentation of every function you are using.

Your forkk is very poorly named, too similar to the very important fork name.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547