I fail at fork 101. I expect this to fork a child process, and output both child and parent printfs:
pid_t fpid;
if ((fpid = fork()) < 0)
{
printf("fork: %s\n", strerror(errno));
exit(-1);
}
if (0 == fpid) // child
{
printf("\nI am the child\n");
}
else
{
printf("\nI am the parent\n");
pid_t wpid;
while ((wpid = waitpid(WAIT_ANY, NULL, 0)))
{
if (errno == ECHILD)
break;
else if (wpid < 0)
printf("wait: %s\n", strerror(errno));
}
}
Instead, I get this output:
I am the parent
wait: Interrupted system call
So my question is: why doesn't the child get a chance to live and run? Won't someone please think of the children! Also, where does the EINTR come from? Obviously, this is somehow related to my first question.
Furthermore, when I run that code in a standalone program, it works correctly, but not when inside a larger program of mine; what could the larger program do to upset waitpid?
FWIW this is on OSX 10.9.
On OSX, it's not legal to do much on the child side of a fork before/without execing. See the caveat at the bottom of the fork man page. The list of safe functions is on the sigaction(2) man page. printf() is not among them.
Also, stdout is likely buffered. The results of the printf() may not be being flushed. It would be flushed if you called exit(), but that's also not legal on the child side of a fork. (It's appropriate to use _exit() but that doesn't flush open streams.) As it is, you don't appear to be exiting your child process, which means flow of execution continues to the caller of the code you've shown, presumably returning to the rest of your program. It may be getting stuck there because of the limitations on the child side of a fork.
You may have more luck if you do something like this in the child:
const char msg[] = "\nI am the child\n";
write(STDOUT_FILENO, msg, sizeof(msg) - 1);
_exit(0);
Finally, I think you should pass fpid rather than WAIT_ANY to waitpid(). You have a specific child process you want to wait for. In the context of a larger program, you don't want to steal the notification of the termination of a child spawned by some other subcomponent. And you always need to loop around interruptible syscalls until they return something other than EINTR.
Only check errno if a failure was indicated, for example by a system call returning -1.
The code should look like this:
pid_t fpid;
if ((fpid = fork()) < 0)
{
printf("fork: %s\n", strerror(errno));
exit(-1);
}
if (0 == fpid) // child
{
printf("\nI am the child\n");
}
else
{
printf("\nI am the parent\n");
pid_t wpid;
while ((wpid = waitpid(WAIT_ANY, NULL, 0)))
{
if (-1 == wpid)
{
perror("waitpid() failed");
}
else if (wpid == fpid)
{
/* My child ended, so stop waiting for it. */
break;
}
}
}
Related
I am writing this question with a bit of a confusion as i feel that I'm missing some point (that's why I am writing it, after all).
So i've been studying how multiple processes access a single file. I have a basic code that makes fork two times - both children fprintf into the same file, the main difference is that one of them sleeps and does much more fprintfs. Child exits when all fprinfs are done. At the same time the parent waitpids, and every time a child terminates it fprintfs into the same file.
What I wanted to see is 1) child process that had more fprintfs and sleep being terminated later then the other child (i think difference in running time should kinda provide a good probability that that would happen) - and that happens; 2) to see first fprintf of a parent process somewhere in the middle of the file as (how i thought!) the first child should be waitpided way before the second one is terminated - that is not what happened.
What happens every time is that both fprintfs are yielded into the file by the parent file at the very end of the file, just like the parent waited until both children are terminated and only then waitpided them.
Exchanging waitpid with wait obviously produced the same result.
I have several guesses:
The second child terminates faster then the parent have time to waitpid the first one and fprintf into the file.
The OS doesn't have time to send SIGCHILD to the parent before the second child terminates.
This is how waitpid works, like maybe signals are queued? (but i haven't found any specification of such functionality).
Could somebody please explain why I am not getting the message about first child terminating in the middle of the file, but do get it at the end?
The code of the program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#define N 1000000
#define SLEEP_TIME 20
int main(void)
{
FILE *fd1 = fopen("test.txt", "w");
pid_t pid1, pid2, cpid;
int wstatus;
pid1 = fork();
if(0 == pid1) {
for(int i = 0; i < N; ++i) {
fprintf(fd1, "child1 %d %d\n", getpid(), i);
}
sleep(SLEEP_TIME);
for(int i = 0; i < N; ++i) {
fprintf(fd1, "child1a %d %d\n", getpid(), i);
}
sleep(SLEEP_TIME);
fclose(fd1);
exit(EXIT_SUCCESS);
}
else if(-1 == pid1) {
exit(EXIT_FAILURE);
}
pid2 = fork();
if(0 == pid2) {
for(int i = 0; i < N/2; ++i) {
fprintf(fd1, "child2 %d %d\n", getpid(), i);
}
fclose(fd1);
exit(EXIT_SUCCESS);
}
else if(-1 == pid2) {
exit(EXIT_FAILURE);
}
while(((cpid = wait(&wstatus)) != -1)) {
//while(((cpid = waitpid(-1, &wstatus, WUNTRACED | WCONTINUED)) != -1)) if(WIFEXITED(wstatus))
fprintf(fd1, "child %d exited with status %d\n", cpid, wstatus);
}
if(errno == ECHILD) {
fprintf(fd1, "All children are waited for!\n");
}
else {
perror("waitpid");
exit(EXIT_FAILURE);
}
fclose(fd1);
exit(EXIT_SUCCESS);
}
The last lines of the resulting file:
2499998 child1a 7359 999997
2499999 child1a 7359 999998
2500000 child1a 7359 999999
2500001 child 7360 exited with status 0 //I wanted this one to be in the middle of the file!
2500002 child 7359 exited with status 0
2500003 All children are waited for!
No, waitpid does return each time a child exits. The problem is that your test is flawed.
On Unix, when you access regular files with stdio functions such as fprintf, by default they are fully buffered. This is desirable when only one process is writing to the file, as it reduces system call overhead, but can be undesirable when timing is important or when trying to synchronize with other processes.
So waitpid is in fact returning immediately after child2 exits, and fprintf is being called at that time, but it doesn't write its message into the the file immediately; rather, it remains buffered in the parent's memory. It will only be written out when the buffer fills up (doesn't happen in the parent, it's usually many KB), or when you call fflush (you don't), or when the file is closed (including on process exit). So both messages are written out together when you call fclose(fd1) in the parent, at which point both children have already exited.
For a test that better illustrates what's happening, disable buffering on this file by calling something like setvbuf(fd1, NULL, _IONBF, 0) immediately after opening the file. Then you should see the "child2 exited" message in the middle of the file, as you expect.
I'm making a shell in C for a school project that is capable of running processes in parallel if it is commanded to do so.
This is the loop of the shell application that waits for commands:
while (1) {
action = parseShellArgs();
if (action == 1) {
printf("Exiting...\n");
break;
} else if (action == 0) {
int pid = fork();
if (pid < 0) {
printf("Failed to fork\n");
} else if (pid == 0) {
(*NUM_PROCESSES_RUNNING)++;
printf("There are %d processes running\n", *NUM_PROCESSES_RUNNING);
char * solverArgs[] = {"a", shellArgs[1], NULL}; // first element is placeholder for argv[0]
execv("CircuitRouter-SeqSolver", solverArgs);
exit(0);
} else if (pid > 0) {
if (*NUM_PROCESSES_RUNNING >= MAXCHILDREN) {
printf("All processes are busy\n");
continue;
}
int status, childpid;
wait(&status);
childpid = WEXITSTATUS(status);
(*NUM_PROCESSES_RUNNING)--;
printf("There are %d processes running\n", *NUM_PROCESSES_RUNNING);
(void)childpid; // suppress "unused variable" warning
} else {
printf("Wait what\n");
}
} else {
printf("Oops, bad input\n");
}
}
Please do disregard the constants being incremented and decremented.
Now, this only works partially. Whenever I give it a command to create another process and run another program (condition action == 0, this has been tested and works), the fork happens and the program is correctly executed.
However, I cannot fork multiple times. What I mean by this is: the program forks and the child executes as instructed in the execv call. The problem is that instead of the parent process then goes back to expecting input to possibly fork again, it waits for the child process to finish.
What I am trying to make this cycle do is for the parent to always be expecting input and forking as commanded, having multiple children if necessary. But as I explained above, the parent gets "stuck" waiting for the single child to finish and only then resumes activity.
Thank you in advance.
Edit: I have experimented multiple combinations of not waiting for the child process, using extra forks to expect input etc.
From man wait.2
The wait() system call suspends execution of the calling process until
one of its children terminates.
Your program gets stuck because that's what wait does. Use waitpid instead with WNOHANG.
waitpid(pid_child, &status, WNOHANG);
doesn't suspend execution of the calling process. You can read the waitpid man page to find out the return values and how to know if a child terminated.
Consider this snippet of code:
void do_child(void);
int main(void){
int n;
pid_t child;
printf("Write a number: ");
scanf("%d", &n);
if(n != 1){
exit(1);
}
child = fork();
if(child >= 0){ /* fork ok */
if(child == 0){
printf("Child pid: %d\n", getpid());
do_child();
_exit(0);
}
else{ /* parent */
printf("Child parent: %d\n", getpid());
_exit(0);
}
}
else{ /* fallito */
perror("No fork");
return 1;
}
return EXIT_SUCCESS;
}
void do_child(void){
/* some code here */
if(1 != 1){
/* what to write here?? _exit or exit*/
}
}
When exiting from a child process it is best to write _exit instead of exit but if i need to call an external function and into this function i want to put an exit, what should i write? _exit or exit?
You can expect exit to call functions registered with atexit. _exit won't do that. Normally, each registered cleanup handler should be executed exactly once, usually in the process in which it was registered. This means that a child process should _exit() and the parent should exit(). If the child process does exec some other program, which is probably the most common case, then that new program will overwrite any registered handlers, which means that you are back to exit().
As to external functions: I'd say you should call exit but you should be prepared to encounter strange behaviour if the parent registers non-trivial stuff atexit before doing the fork. So try to fork early unless you mean to exec in the child. And have an eye on what exit handlers your own code and the libraries you use might install. I/O buffer flushing is one example.
exit() terminates after cleanup whereas _exit() terminates immediately.
I would suggest that under normal circumstances, exit() is the correct approach - although I am sure you will understand what you are doing if you chose _exit()?!
I'll cite MSDN online as it's in my favourites :)
I'm creating background processes in C using fork().
When I created one of these processes, I add its pid to an array so I can keep track of background processes.
pid = fork();
if(pid == -1)
{
printf("error: fork()\n");
}
else if(pid == 0)
{
execvp(*args, args);
exit(0);
}
else
{
// add process to tracking array
addBGroundProcess(pid, args[0]);
}
I have a handler for reaping zombies
void childHandler(int signum)
{
pid_t pid;
int status;
/* loop as long as there are children to process */
while (1) {
/* get zombie pids */
pid = waitpid(-1, &status, WNOHANG);
if (pid == -1)
{
if (errno == EINTR)
{
continue;
}
break;
}
else if (pid == 0)
{
break;
}
/* Remove this child from tracking array */
if (pid != mainPid)
cleanUpChild(pid);
}
}
When I create a background process, the handler is executing and attempting to clean up the child before I can even make the call to addBGroundProcess.
I'm using commands like emacs& which should not be exiting immediately.
What am I missing?
Thanks.
You're right, there is a race condition there. I suggest that you block the delivery of SIGCHLD using the sigprocmask function. When you have added the new PID to your data structure, unblock the signal again. When a signal is blocked, if that signal is received, the kernel remembers that it needs to deliver that signal, and when the signal is unblocked, it's delivered.
Here's what I mean, specifically:
sigset_t mask, prevmask;
//Initialize mask with just the SIGCHLD signal
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
sigprocmask(SIG_BLOCK, &mask, &prevmask); /*block SIGCHLD, get previous mask*/
pid = fork();
if(pid == -1)
{
printf("error: fork()\n");
}
else if(pid == 0)
{
execvp(*args, args);
exit(0);
}
else
{
// add process to tracking array
addBGroundProcess(pid, args[0]);
// Unblock SIGCHLD again
sigprocmask(SIG_SETMASK, &prevmask, NULL);
}
Also, I think there's a possibility that execvp could be failing. (It's good to handle this in general, even if it's not happening in this case.) It depends exactly how it's implemented, but I don't think that you're allowed to put a & on the end of a command to get it to run in the background. Running emacs by itself is probably what you want in this case anyway, and putting & on the end of a command line is a feature provided by the shell.
Edit: I saw your comments about how you don't want emacs to run in the current terminal session. How do you want it to run, exactly - in a separate X11 window, perhaps? If so, there are other ways of achieving that.
A fairly easy way of handling execvp's failure is to do this:
execvp(*args, args);
perror("execvp failed");
_exit(127);
Your code just catches the exit of the child process it fork'ed, which is not to say that another process wasn't fork'ed by that child first. I'm guessing that emacs in your case is doing another fork() on itself for some reason, and then allowing the initial process to exit (that's a trick daemons will do).
The setsid() function might also be worth looking at, although without writing up some code myself to check it I'm not sure if that's relevant here.
You should not be using the shell with & to run background processes. If you do that, they come out as grandchildren which you cannot track and wait on. Instead you need to either mimic what the shell does to run background processes in your own code, or it would probably work just as well to close the terminal (or rather stdin/out/err) and open /dev/null in its place in the child processes so they don't try to write to the terminal or take control of it.
Hi I'm working on a unix shell and I'm running into two problems. I was wondering if any of you could help me out. My first problem is that the shell is not waiting for the child process to terminate. I can actually go type more commands while the child process is running. My second problems is in the following two lines. I'm not getting any display on the shell.
fprintf(stderr, "Process name is: %s\n", commandArgv[0]);
fprintf(stderr, "Child pid = %d\n", pid);
I have the following method to execute a process entered by the user: i.e. firefox, ls -a, etc
void execute(char *command[], char *file, int descriptor){
pid_t pid;
pid = fork();
if(pid == -1){
printf("error in execute has occurred\n");
}
if(pid == 0){
execvp(*command,command);
fprintf(stderr, "Process name is: %s\n", commandArgv[0]);
fprintf(stderr, "Child pid = %d\n", pid);
wait(&status);
exit(EXIT_SUCCESS);
}
else{
printf("ignore for now\n");
}
}
This is where I call the execute command. It works fine and launches a process, but it doesn't wait for it to finish.
execute(commandArgv, "STANDARD",0);
Do you guys have any idea what I might be doing wrong? Thanks I really appreciate any time you take to help me on this.
Once execvp() runs, it will never return. It replaces in-memory the running app with whatever was provided. So your fprintf() and wait() are in the wrong place.
Other than getting the actual logic worked out correctly (Stéphane's suggestions all good) you might also want to fflush(stderr) after fprintf-ing, to ensure your error messages make it out right away instead of being buffered.
You have a little error in how the process works. After execvp is called, there is no turning back. fork() gives you have the parent and an identical child, but execvp overwrite child image to be the command you are calling.
The execvp returns only when a severe errors occur that prevent overwriting the image. So, you need to print things before its call. So you also may want to change the EXIT_SUCCESS to an EXIT_FAILURE there.
Now there is another mistake using wait: you always want the parent waiting for the child, not the other way around. You cannot ask for the child to wait. She has nothing to wait, she will run and terminate. So, you need to move the wait() call to the else part.
void execute(char *command[], char *file, int descriptor)
{
pid_t pid;
pid = fork();
if(pid == -1)
{
printf("fork() error in execute() has occurred\n");
return; /* return here without running the next else statement*/
}
if(pid == 0)
{
fprintf(stderr, "Process name is: %s\n", commandArgv[0]);
fprintf(stderr, "Child pid = %d\n", getpid());
execvp(*command,command);
fprintf(stderr, "Error! Can't overwrite child's image!\n");
exit(EXIT_FAILURE);
}
else
{
printf("Parent waiting for child pid: %d\n", pid);
wait(&status);
printf("Parent running again\n");
}
}
But reading your question, maybe you actually don't want the parent to wait. If that is the case, just don't use the wait() function.
Take care,
Beco
Edited: some minor mistakes. pid of child is getpid()