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
(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.