fork() - multiple processes and system calls - c

I am writing a mapreduce program that uses multiple I/O pipes (one pipe per process) to get some final results. I am having a problem with creating the processes. Specifically, I am getting the following error:
wait error: Interrupted system call
This is my code that spawns processes:
while (values[inc]!=NULL) //provided array of text lines
{
if ((pid = fork()) == -1) {
perror("fork error");
exit(EXIT_FAILURE);
}
else if (pid == 0) { /* start of child process */
printf("Child process...\n");
/* pipes[inc][1] is a file descriptor to which myMap writes some data
using the write() system call
mr is a struct that holds other function pointers */
mr->myMap(pipes[inc][1],values[inc]);
exit(0);
}
else { /* start of parent process */
printf("Parent process...\n");
if ((wpid = wait(&status)) == -1)
/* Wait for child process. */
perror("wait error");
else { /* Check status. */
if (WIFSIGNALED(status) != 0)
printf("Child process ended because of signal %d\n",
WTERMSIG(status));
else if (WIFEXITED(status) != 0)
printf("Child process ended normally; status = %d\n",
WEXITSTATUS(status));
else
printf("Child process did not end normally\n");
}
//close(fd[1]);
printf("Parent process ended\n");
}
inc++;
}
After this I am creating one thread
pthread_t newThread;
pthread_create(&newThread,NULL,threadFunction,values);
pthread_join(newThread,NULL);
The threadFunction uses select() function to find out which file descriptor is ready to be read and reads it and puts data in a dictionary.
When running form gdb debugger, the program output:
Parent process...
Child process...
wait error: Interrupted system call
Parent process ended
Parent process...
Child process ended normally; status = 0
Parent process ended
Parent process...
Child process...
Child process...
wait error: Interrupted system call
Parent process ended
I don't know how to resolve the issue. Any suggestions?
Thanks!

You need to put your wait() call into a loop and if it returns an error (-1) and errno == EINTR continue the loop. Any other error is a real error and should be treated as such.
Things like profiling timers can cause signals to be sent to the process, however the signal probably causing the interruption is SIGCHLD, which as you know is called when a child process changes state.
EDIT: OK, I'll write the answer in code:
do
{
wpid = wait(&status);
}
while (wpid == -1 && errno == EINTR);
if (wpid == -1)
{
perror("wait error");
return -1;
}
else
{
// we have wait status
...
}

Related

How to Execute Shell Script in C Programming, Receive Feedback and Processor ID, and Close Process

I am writing a program that needs to fire another program for a number of seconds, then close it.
Feedback from the program's console would be useful, if possible.
I imagine I would close the program by retrieving the pid from the child process and running a pkill?
What would be the best way to go about this?
Thanks in advance
EDIT BY OP
void mountAd(char* adFilePath){
char* mountPoint = getNextAvailableMount();
// Set Playlist ready to be played
editPlaylist(mountPoint, adFilePath);
// Fork process and fire up ezstream
int pid = fork();
if(pid == 0){
puts ("Child Process Here\n");
execl ("/usr/local/bin/ezstream","/usr/local/bin/ezstream", "-c", "/home/hearme/radio/_test_adverts/advert01.xml", NULL);
perror("execl");
} else {
puts ("Parent Process Here\n");
}
// Advised sleep for 3 seconds until ezstream has started
sleep(3);
// More stuff to do here later
kill(pid, SIGTERM);
waitpid(pid, NULL, 0);
}
Something like this should work:
pid = fork();
if (pid < 0)
/* fork failed, error handling here */
if (pid == 0) {
/* we are the child, exec process */
execl(...);
/* this is only reached if execl fails */
perror("execl");
/* do not use exit() here, do not return from main() */
_Exit(EXIT_FAILURE);
}
/* we are the parent */
sleep(duration);
kill(pid, SIGKILL);
/* use wait/waitpid/waitid as needed */
waitpid(pid, NULL, 0);
Notice that this does not correctly perform error checking for the case when the program you want to run cannot be found or executed, a more elaborate scheme is needed for that case, if you are interested I could elaborate.

whether a function returned in the child process can be captured in the parent process

I'm currently implementing the && function in a shell using C. For example, if we input cmd1 && cmd2, then cmd2 executes only when cmd1 exits successfully. I'm thinking about:
int main() {
int i;
char **args;
while(1) {
printf("yongfeng's shell:~$ ");
args = get_line();
if (strcmp(args[0], "exit") == 0) exit(0); /* if it's built-in command exit, exit the shell */
if('&&') parse_out_two_commands: cmd1, cmd2;
if (execute(cmd1) != -1) /* if cmd1 successfully executed */
execute(cmd2); /* then execute the second cmd */
}
}
int execute(char **args){
int pid;
int status; /* location to store the termination status of the terminated process */
char **cmd; /* pure command without special charactors */
if(pid=fork() < 0){ //fork a child process, if pid<0, fork fails
perror("Error: forking failed");
return -1;
}
/* child */
else if(pid==0){ /* child process, in which command is going to be executed */
cmd = parse_out(args);
/* codes handleing I/O redirection */
if(execvp(*cmd, cmd) < 0){ /* execute command */
perror("execution error");
return -1;
}
return 0;
}
/* parent */
else{ /* parent process is going to wait for child or not, depends on whether there's '&' at the end of the command */
if(strcmp(args[sizeof(args)],'&') == 0){
/* handle signals */
}
else if (pid = waitpid(pid, &status, 0) == -1) perror("wait error");
}
}
So I'm using another function int execute(char ** args) to do the actual work. Its return type is int because I wan to know whether the command exits successfully. But I'm not sure here whether the parent process can get the return value from the child since they're two different processes.
Or should I decide whether to execute the second command in the child process, by forking another process to run it? Thanks a lot.
Change:
if(pid=fork() < 0){ //fork a child process, if pid<0, fork fails
to:
if((pid=fork()) < 0){ //fork a child process, if pid<0, fork fails
You're setting pid to the result of fork() < 0, not setting it to the PID of the child. So unless there's an error in fork(), this sets pid to 0 in both the parent and child, so they both think they're the child.
Regarding the return value of the execute() function: It will return in both the parent and child. In each process, it will return whatever was specified in the return statement in the corresponding branch of the if in execute(). Note that it execve() is successful, the child never returns, because it's no longer running this program, it's running the program that was exec'ed.
If the child wants to send success or failure information to the parent, it does this using its exit status, by calling exit(0) to indicate success, and exit(some-nonzero-value) to indicate failure. The parent can get the exit status using waitpid, and then return a success or failure indication from execute().

How to make parent wait for all child processes to finish?

I'm hoping someone could shed some light on how to make the parent wait for ALL child processes to finish before continuing after the fork. I have cleanup code which I want to run but the child processes need to have returned before this can happen.
for (int id=0; id<n; id++) {
if (fork()==0) {
// Child
exit(0);
} else {
// Parent
...
}
...
}
pid_t child_pid, wpid;
int status = 0;
//Father code (before child processes start)
for (int id=0; id<n; id++) {
if ((child_pid = fork()) == 0) {
//child code
exit(0);
}
}
while ((wpid = wait(&status)) > 0); // this way, the father waits for all the child processes
//Father code (After all child processes end)
wait waits for a child process to terminate, and returns that child process's pid. On error (eg when there are no child processes), -1 is returned. So, basically, the code keeps waiting for child processes to finish, until the waiting errors out, and then you know they are all finished.
POSIX defines a function: wait(NULL);. It's the shorthand for waitpid(-1, NULL, 0);, which will suspends the execution of the calling process until any one child process exits.
Here, 1st argument of waitpid indicates wait for any child process to end.
In your case, have the parent call it from within your else branch.
Use waitpid() like this:
pid_t childPid; // the child process that the execution will soon run inside of.
childPid = fork();
if(childPid == 0) // fork succeeded
{
// Do something
exit(0);
}
else if(childPid < 0) // fork failed
{
// log the error
}
else // Main (parent) process after fork succeeds
{
int returnStatus;
waitpid(childPid, &returnStatus, 0); // Parent process waits here for child to terminate.
if (returnStatus == 0) // Verify child process terminated without error.
{
printf("The child process terminated normally.");
}
if (returnStatus == 1)
{
printf("The child process terminated with an error!.");
}
}
Just use:
while(wait(NULL) > 0);
This ensures that you wait for ALL the child processes and only when all have returned, you move to the next instruction.

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);
}
}

Avoid zombies when father is in a wait of a semaphore

This is a strange question. I have 2 different program:
server and client.
server start, alloc all the message queue and start to waitin for a signal from client (the signal is for tell to the server that "there are new message").
the server remain in an infinite loop until recive SIGQUIT.
the client, when casted, start to send a huge number of message to the server
for(;;){//infinite loop
wait(sem,1); //wait for new message
rc = msgctl(msgid, IPC_STAT, &qbuff);
seq_num++;
pid=fork(); //new process for take the message
if(!pid){
if((msgrcv(msgid, &q, msgsz, 1,MSG_NOERROR))== -1)
perror("msgrcv error");
else{
pthread_mutex_lock(&mutex); //start critic sector
printf("\nthere is a prenotation\n");
q.price=get_conf_value(q.kindof_service)+(q.priority*get_conf_value(3)); //costo = costo_visita + (priorità * costo_priorità)
q.turn=seq_num-q.priority; //assign turn
pthread_mutex_unlock(&mutex); //end critic sector
if(q.turn<0)q.turn=0; //controllo del turno che non sia minore di 0
printf("---------------------------");
printf("\nPrenotation number %i\npid caller: %i\npriorità: %i\n for %i\ncost %i\nturn %i\n",seq_num,q.clientId,q.priority, q.kindof_service ,q.price, q.turn);
printf("---------------------------\nPrenotation ok\n\n\n");
}
printf("\nsuccess.\n");
exit(1); //close children process
}
}
The problem is that, in this way the father leave so much zombies. If i add
else{//i am the father
waitpid(pid, 0, 0);
}
there is the problem that the primary process fork, then wait until the child is ended, then fork again.
i need that the father fork so many time and that dont wait the end of the process before fork again.
But without the waitpid the problem is another.. because after that he start all the process needed for receive all the message, the father take the control and still waitin for another signal from the client (the first wait(sem,1) ), leaving so much zombie process.
I don't know if I explained it well.. is very difficult in english -_-
So, i want a server that, received the signal, fork many many times. any child take a message and do some stuff, then the child end. Meanwhile the server continue to wait for new incoming message. All without make zombies :)
One way to fire-and-forget processes without having to worry about zombies is to fork twice.
Each process has a parent process. If the parent process exits before the child does, the child is becoming an orphan, and is inherited by init (process 1) - which will wait for all children, preventing them to become zombies without manual work.
So what you can do is to fork, and fork yet again in the child process. Then, you can let the child exit, which will cause the grandchild (where you do your work) to be inherited by init. The parent process can wait for the child (which won't take long, because the child did nothing else than fork and exit). When the grandchild is exiting, init will automatically wait for it.
/* fire and forget */
int execute_detached(char **cmdline)
{
pid_t pid;
if((pid = fork()) < 0) { /* fork error */
perror("fork");
return 0;
}
else if(pid > 0) { /* parent */
waitpid(pid, NULL, 0);
return 1;
}
else { /* child */
if((pid = fork()) < 0) { /* fork error */
perror("fork");
return 0;
}
else if(pid > 0) { /* child */
/* make grand child an orphan */
_exit(0);
}
else { /* grand child */
execvp(cmdline[0], cmdline);
perror("execvp");
_exit(1);
}
}
return 0;
}

Resources