double fork causes socket in original parent to break - c

I do a double fork (fork, then the child forks again, I wait for the child, the grandchild is handled by init) in a process and after the child has closed I try to read from a socket that I had open in the parent previous to the fork. The read fails every time I run the program.
The message is being sent using sendto() which returns an error code of ENOENT.
Should this be working or am I [10]?
Here is the code in the function that forks:
uint8_t
upgrade(
char *server,
char *file)
{
pid_t pid1, pid2;
int status;
if ((pid1 = fork()) < 0)
{
/* Fork error */
log("FAILED: First fork() failed");
}
else if (pid1 == 0)
{
/* First child */
if ((pid2 = fork()) < 0)
{
/* Fork error */
log("FAILED: Second fork() failed");
exit(0);
}
else if (pid2 == 0)
{
/*
execl("/usr/sbin/system_upgrade",
"system_upgrade", NULL);
*/
exit(0);
}
else
{
/* Second parent ie. First child
* Note: Exit cleanly so that second child
* gets reparented to init, and we avoid a zombie process */
exit(0);
}
}
else
{
/* First parent, wait for first child to exit */
if (waitpid (pid1, &status, 0) != pid1)
{
log("FAILED: waitpid() failed");
}
} /* FORK */
return OK;
}
edit: removed extra bracket, fixed indentation, marked it as code again

Related

How to signal from parent process to the child?

How can i send signal from parent process to the child?
After i write to the pipe i want to send signal to the child process.
pid_t pid;
int filds[2];
pipe(filds);
char *args[150] = {"./draw.out", NULL};
char buff = '\0';
if ((pid = fork()) < 0) { // fork a child process/
printf("*** ERROR: forking child process failed\n");
exit(1);
} else if (pid == 0) {
execvp(args[0], args); // execute the command
} else { // for the parent
char btnPressed = getch();
while (btnPressed != 'q'){
btnPressed = getch();
write(filds[1],buff, BUFF_SIZE);
//signal
}
// signal finish game.
}
kill(PID, SIGwhatever);
however this is probably a poor choice; the better solution is
close(filds[1]);
and handle close of input in the child. I think you're missing a
dup2(files[0],0);
in the child path as well.

what happens to child process if it execvp() is successful?

I have a question about the use of execvp(), for the following function, if I am in child process and the execvp() function is executed successfully (according to the man page, it will not return), if the script outside of else {} will keep working, which means if the execCmd() function will return any value?
int execCmd(char* args[10]) {
pid_t pid = fork();
if (pid < 0) {
exit(1);
} else if (pid > 0) { // parent process
/* do something */
} else {
if (execvp(*args, args) < 0) {
printf("Execution Failed!");
exit(1);
}
}
return 0;
}
Thanks in advance!
If execvp is successful, the process starts executing the specified program.
Parent Process Child Process
------------------- -------------------
fork()
pid_t pid = ...; pid_t pid = ...;
pid < 0 pid < 0
pid > 0 pid > 0
/* do something */ execvp(*args, args)
return 0; [main of new program]
Your program could have been written
int execCmd(char** args) {
pid_t pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
}
if (pid == 0) {
execvp(*args, args);
perror("execvp");
_exit(1);
}
/* ... Do something in parent ... */
return 0;
}
Also, you probably want to wait for the child to finish, return the pid or have the child auto-reap (by making SIGCHILD ignored).
in general, the code should not be executing misc statements;
The code should only need to test the results of the call to fork() once.
Notice, there is no need to wrap the call to execvp() in an if() code block
The parent process should wait for the child process to complete before exiting.
When an error occurs, should output an error message to stderr via a call to fprintf( stderr, "...\n" ) However, when the error is from a system function, the reason the system thinks the error occurred should also be output to stderr. A simple way to accomplish this is by calling perror()
for ease of readability and understanding: separate code blocks ( for if else while do...while switch case default ) via a single blank line.
the preferred code logic for a call to fork() is:
int execCmd(char* args[10])
{
pid_t pid;
switch( pid = fork() )
{
case -1: // error
perror( "fork failed" );
exit(1);
break;
case 0: // child
execvp(*args, args);
perror( "execvp Failed!" );
exit(1);
break;
default: // parent
/* do something */
waitpid( pid, NULL );
break;
}
return 0;
}

Creating a UNIX Shell, confused about fork and child pids?

Here is my code for the evaluate function, which is called in the main.
void eval(char *cmdline)
{
char *argv[MAXARGS]; /* argv for execve() */
int bg; /* should the job run in bg or fg? */
pid_t pid; /* process id */
bg = parseline(cmdline, argv);
struct job_t tempJob;
if (builtin_cmd(argv) == 0)
{
if ((pid = fork()) == 0)
{ /* child runs user job */
if (execve(argv[0], argv, environ) < 0)
{
printf("%s: Command not found.\n", argv[0]);
exit(0);
}
}
if (!bg)
{ /* parent waits for fg job to terminate */
int status;
if (waitpid(pid, &status, 0) < 0)
unix_error("waitfg: waitpid error");
}
else /* otherwise, don’t wait for bg job */
{
printf("%d %s", pid, cmdline);
}
}
return;
}
Now when I run a background job, I expect that the pid of the job get printed twice twice, once in parent and once for child.I just need to understand what is going on in the code. It works the way it is supposed to but why?
Both the parent and child return from fork, but the condition == 0 is true only for the child:
if ((pid = fork()) == 0)
Thus only the child runs this:
if (execve(argv[0], argv, environ) < 0)
execve replaces the current process, and thus does not return if there is no error, i.e., the child's execution of this program ends either here or at the exit(0); that follows from the error condition.
The rest of the function is run only by the parent in all cases.

Interprocess Communication fork() - Timing wait() and/or sleep()

I've been asked to develop the consumer (client) side to a producer (server), where the producer creates processes, waits until the consumer has read shared memory and deleted processes, then passes control back to the producer for the killing of processes and the shutting down of the shared memory block.
I've researched the difference between sleep and wait, and realise that as soon as fork() is called, the child process begins running.
The below code is after the creation of processes and checks if they're parent processes. If they are, they wait(0). *Now for my question, how do I know where the code in the consumer starts to be executed, and how do I pass it back? *
else if(pid > 0)
{
wait(0);
}
Below can be seen the main loop the producer uses.
int noToCreate = atoi(argv[2]); // (user inputs on cmd line "./prod 20 10 5" - 20 size of shared mem, 10 process to be created, 5 processes to be deleted)
while(*memSig != 2)
{
while(*memSig == 1) // set memsignature to sleep while..
{
sleep(1);
}
for(B = 0; B < noToCreate; B++)
{
pid = fork();
if(pid == -1)
{
perror("Error forking");
exit(1);
}
else if(pid > 0)
{
wait(0);
}
else
{
srand(getpid());
while(x == 0)
{
if(*randNum == 101)
{
*randNum = rand() % (100 -
1) + 1;
*pidNum = getpid();
printf("priority: %d
Process ID: %d \n", *randNum, *pidNum);
x = 1;
}
else
{
*randNum++;
*pidNum++;
}
}
exit(0);
}
} /* Closes main for loop */
if(*memSig == 0)
{
*memSig = 1;
}
} /* Closes main while loop */
Thanks a bunch guys :)
wait make parent blocked until any child end .You can use waitpid let parent wait specific child.
When a child process end, it will set a signal SIG_CHILD.
The pid is zero for the child process after the fork, so you are in the child process at your call to the srand function.
The other pid is that for the child process which allows he original thread to wait for the child to finish. If you wish to pass data between the processes consider using a pipe. A popen call returns two file descriptors, one to write end and the other to the read end. Set this up before the fork and the two processes can communicate.
wait makes the parent wait for any child to terminate before going on (preferably use waitpid to wait for a certain child), whereas sleep puts the process to sleep and resumes it, as soon as the time passed as argument is over.
Both calls will make the process block.
And it is NOT said that the child will run immediately, this is indeterminate behavior!
If you want to pass data between producer and consumer, use pipes or *NIX sockets, or use the return-value of exit from the child if a single integer is sufficient.
See man wait, you can get the return value of the child with the macro WEXITSTATUS.
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
pid_t cpid, w;
int status;
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Code executed by child */
printf("Child PID is %ld\n", (long) getpid());
if (argc == 1)
pause(); /* Wait for signals */
_exit(atoi(argv[1]));
} else { /* Code executed by parent */
do {
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
exit(EXIT_SUCCESS);
}
}

how can I get the return value of a program executed by exec? [duplicate]

This question already has answers here:
How to get the return value of a program ran via calling a member of the exec family of functions?
(6 answers)
Closed 8 years ago.
I have this c code:
if(fork()==0){
execl("/usr/bin/fsck", "fsck", "/dev/c0d0p1s0", NULL);
}
it calls execl to run fsck for checking the filesystem /dev/c0d0p1s0.
My question is: how can I get the return value of fsck?
I need the return value of fsck to check whether the file system is consistence or not.
Thank you.
Have the parent process wait for the child to exit:
pid_t pid = fork();
if (pid == -1) {
// error, no child created
}
else if (pid == 0) {
// child
}
else {
// parent
int status;
if (waitpid(pid, &status, 0) == -1) {
// handle error
}
else {
// child exit code in status
// use WIFEXITED, WEXITSTATUS, etc. on status
}
}
You must call wait() or waitpid() in the parent process and it will give you the exit status of the program executed by execl(). Not calling one of these will make the child process remain a zombie when it terminates, i.e. a process that is dead but stays in the process table because its parent wasn't interested in its return code.
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
...
pid_t pid;
int status;
if ((pid = fork()) == 0) {
/* the child process */
execl(..., NULL);
/* if execl() was successful, this won't be reached */
_exit(127);
}
if (pid > 0) {
/* the parent process calls waitpid() on the child */
if (waitpid(pid, &status, 0) > 0) {
if (WIFEXITED(status) && !WEXITSTATUS(status)) {
/* the program terminated normally and executed successfully */
} else if (WIFEXITED(status) && WEXITSTATUS(status)) {
if (WEXITSTATUS(status) == 127) {
/* execl() failed */
} else {
/* the program terminated normally, but returned a non-zero status */
switch (WEXITSTATUS(status)) {
/* handle each particular return code that the program can return */
}
}
} else {
/* the program didn't terminate normally */
}
} else {
/* waitpid() failed */
}
} else {
/* failed to fork() */
}
The _exit() call in the child is to prevent it from continuing execution in case execl() fails. Its return status (127) is also necessary to distinguish the case of an eventual execl() failure in the parent.

Resources