0

So I have this simple program that sleeps for 4 second if the value returned by fork is '0' meaning that the child process is executing, I've tried using sleep in child process but the program is blocked, and flushing standard output isn't working... code:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char const *argv[]) {
  pid_t value = fork();

  if (value == 0) {
    sleep(4);
  }
  
  printf("Value returned by fork: %d\n", value);
  printf("I'm the process N°%d\n", getpid());
  
  return 0;
}

I'm running on Ubuntu 20.04.3 LTS.

Output:

Value returned by fork: 12618
I'm the process N°12617\
farouk@farouk-HP-Pavilion-Desktop-TP01-1xxx:~/sysexp$  Value returned by fork: 0
I'm the process N°12618

enter image description here

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Farouk Hamadi
  • 31
  • 1
  • 8
  • What output are you getting? What are you expecting? – Shawn Apr 23 '22 at 20:17
  • 1
    Totally tangential to the main problem — Since you are not using either `argc` or `argv`, it would be better to use `int main(void)` in this program. – Jonathan Leffler Apr 23 '22 at 20:20
  • You should see the output from the parent and then your command line prompt; then 4 seconds later, you should get output from the child. If that's not what's happening, maybe your shell has prevented the child from writing to the terminal (see SIGTTOU etc from ``). What happens if you hit return? Which platform (o/s, version) are you using? It works without any signal issues for me on macOS Monterey 12.3.1 with Bash as my shell. – Jonathan Leffler Apr 23 '22 at 20:23
  • @JonathanLeffler You're right I was just using the template main function that my editor provided – Farouk Hamadi Apr 23 '22 at 20:26
  • @Shawn I'm expecting the program to terminate when value of fork is 0, but sleep seems to freeze it – Farouk Hamadi Apr 23 '22 at 20:26
  • You could delay the parent process's exit using a `wait()` loop: `int corpse; int status; while ((corpse = wait(&status)) > 0) printf("%d: Child %d exited with status 0x%.4X\n", getpid(), corpse, status);` — and you'd need `#include ` too. – Jonathan Leffler Apr 23 '22 at 20:28
  • I'm using Ubuntu 20.04.3 LTS and I'll update the post with the output I'm getting – Farouk Hamadi Apr 23 '22 at 20:29
  • 1
    The child's `sleep(4);` puts it to sleep for 4 seconds, but the child process continues afterwards and executes the two `printf()` statements before exiting. – Jonathan Leffler Apr 23 '22 at 20:29
  • 1
    The parent will exit after printing two lines; the child will wait 4 seconds, then exit after printing two lines – Shawn Apr 23 '22 at 20:30
  • 3
    Your output screenshot looks correct. – Shawn Apr 23 '22 at 20:31
  • You just need to type a command after the child's output (e.g. `ls`) or even just hit return to get another prompt. Or put the wait loop into the code so that the parent doesn't exit until the child has exited. – Jonathan Leffler Apr 23 '22 at 20:32
  • 1
    Please put the output into the question as text, not as an image. – Jonathan Leffler Apr 23 '22 at 20:32
  • Isn't it supposed to stop executing, I have to ctrl + c to stop the process – Farouk Hamadi Apr 23 '22 at 20:32
  • 2
    Why do you think it didn't stop executing? Is it because you didn't see a new shell prompt after four seconds? The shell only prompts once after each command. The parent process printed its lines immediately, then the parent died, and the shell printed its prompt. As far as the shell knows, when the parent terminates, the command is finished. Four seconds later the child printed its lines, but the shell never knew that the child exists. – Solomon Slow Apr 23 '22 at 20:33
  • 2
    It's exited. You can hit return to see that the shell is waiting for your input. A control-C interrupt makes the shell respond again. Your shell prompt is interleaved with the output from the program because you don't make the parent wait. You could type `ps` to see the commands that are running; the one identified as the child (and the one identified as the parent) will both be missing. You could type the `ps` before the child's output appears (in the 4 second gap) and you might see the child running. – Jonathan Leffler Apr 23 '22 at 20:33
  • @SolomonSlow Yes that's what I thought – Farouk Hamadi Apr 23 '22 at 20:35
  • 2
    Nothing is blocked. We're conditioned to think that if we don't see the shell prompt at the start of the line, it must be because some other program is in the foreground. But in this case, the shell already printed its prompt and is still waiting for your input, it's just that the background child process spammed more output to the terminal in the meantime. – Nate Eldredge Apr 23 '22 at 20:38
  • @JonathanLeffler I've tried the process status command and everything is working as expected, Thank you!! – Farouk Hamadi Apr 23 '22 at 20:39

1 Answers1

1

To allow this question to have an accepted answer.

The child process is not blocking the shell. The shell gave its prompt and the child wrote some output after the prompt, leaving the cursor at the start of a line without a shell prompt visible — because the shell prompt already appeared earlier.

There are a variety of ways around this.

The simplest is just to type a command such as ps and hit return, noting that the shell executes it, and that the ps output does not list the child process. If you type the ps command quick enough, you might see the child listed in the output before its output appears.

Another is to modify the program so that it waits for all child processes to exit before it exits — using wait() or waitpid(). The same code can be used in the child and the parent since the child will have no children of its own. The call to the wait function will return immediately with a 'no more children' status (error).

You can find extensive discussion of all this in the comments — I've chosen to make this a Community Wiki answer since there was a lot of activity in the comments that identified the gist of this answer.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278