Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>It would probably be more beneficial for you provide what you have so far and explain what doesn't work as expected but here is what I came up with:</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;sys/types.h&gt; #include &lt;unistd.h&gt; #include &lt;signal.h&gt; #include &lt;stdlib.h&gt; #define READY_SIGNAL SIGUSR1 /* The ready flag is set when READY_SIGNAL is received. * It is needed so that when we wake up from sigsuspend * we know whether or not the signal received was READY_SIGNAL. */ volatile sig_atomic_t ready; void make_ready(int i) { ready = 1; } int main (int argc, char *argv[]) { pid_t cpid, ppid; /* pids of the child and parent */ /* Signal masks for sigprocmask and sigsuspend */ sigset_t block_mask, wait_mask; unsigned long c = 1; /* The counter */ unsigned long n = 100; /* The default max count value */ struct sigaction act; /* Override the default max count if provided */ if (argv[1]) n = strtoul(argv[1], NULL, 10); /* Prepare signal masks */ sigemptyset(&amp;wait_mask); sigemptyset(&amp;block_mask); sigaddset(&amp;block_mask, READY_SIGNAL); /* Set the signal mask for the parent to ignore READY_SIGNAL until * we are ready to receive it, the mask will be inherited by the child, * needed to avoid race conditions */ sigprocmask(SIG_BLOCK, &amp;block_mask, NULL); /* Register the signal handler, will be inherited by the child */ act.sa_flags = 0; act.sa_handler = make_ready; sigemptyset(&amp;act.sa_mask); sigaction(READY_SIGNAL, &amp;act, NULL); /* Get the parent's process id, needed for the child to send signals * to the parent process, could alternatively use getppid in the child */ ppid = getpid(); /* Call fork, storing the child's process id needed for the parent to * send signals to the child */ cpid = fork(); if (cpid &lt; 0) { perror("Fork failed"); exit(EXIT_FAILURE); } if (cpid == 0) { /* Child */ c = 2; /* Child's first number will always be 2 */ if (c &gt; n) exit(0); /* If c &gt; n we have nothing to do */ do { /* Suspend until we receive READY_SIGNAL */ while (!ready) sigsuspend(&amp;wait_mask); /* Print out number, flush for proper output sequencing when output is not a terminal. */ printf("Child: %lu\n", c); fflush(stdout); ready = 0; /* Reset ready flag */ c += 2; /* Increment counter */ /* Wake up parent process */ kill(ppid, READY_SIGNAL); } while (c &lt;= n); } else { /* Parent */ for (;;) { /* Print out number, flush for proper output sequencing when output is not a terminal. */ printf("Parent: %lu\n", c); fflush(stdout); c += 2; /* Increment counter */ kill(cpid, READY_SIGNAL); /* Wake up child process */ if (c &gt; n) break; /* Don't go back to sleep if we are done */ ready = 0; /* Reset ready flag */ /* Suspend until we receive READY_SIGNAL */ while (!ready) sigsuspend(&amp;wait_mask); }; wait4(cpid, NULL, 0); /* Don't exist before child finishes */ } return 0; } </code></pre> <p>This passes these basic tests:</p> <p><code>./print_with_signals 100000|sort -n -k 2 -c &amp;&amp; echo "Success"</code> <br/> <code>./print_with_signals 100001|sort -n -k 2 -c &amp;&amp; echo "Success"</code></p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload