#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
/* Expected order is:
* Child signals parent
* Parent got signal
* Child will exit now
*
* The bug we test for: under strace -f, last two lines are swapped
* because wait syscall is suspended by strace and thus can't be interrupted.
*/
static const char msg1[] = "Child signals parent\n";
static const char msg2[] = "Parent got signal\n";
static const char msg3[] = "Child will exit now\n";
static void handler(int s)
{
write(1, msg2, sizeof(msg2)-1);
}
static void test()
{
/* Note: in Linux, signal() installs handler with SA_RESTART flag,
* therefore wait will be restarted.
*/
signal(SIGALRM, handler);
if (fork() == 0) {
/* child */
sleep(1);
write(1, msg1, sizeof(msg1)-1);
kill(getppid(), SIGALRM);
sleep(1);
write(1, msg3, sizeof(msg3)-1);
_exit(0);
}
/* parent */
wait(NULL);
_exit(0);
}
int main()
{
char buf1[80];
char buf2[80];
char buf3[80];
int pipefd[2];
printf("Please run me under 'strace -f'\n");
pipe(pipefd);
if (fork() == 0) {
if (pipefd[1] != 1) {
dup2(pipefd[1], 1);
close(pipefd[1]);
}
test();
}
if (pipefd[0] != 0) {
dup2(pipefd[0], 0);
close(pipefd[0]);
}
fgets(buf1, 80, stdin); printf("%s", buf1);
fgets(buf2, 80, stdin); printf("%s", buf2);
fgets(buf3, 80, stdin); printf("%s", buf3);
if (strcmp(buf1, msg1) != 0
|| strcmp(buf2, msg2) != 0
|| strcmp(buf3, msg3) != 0
) {
printf("ERROR! Expected order:\n%s%s%s", msg1, msg2, msg3);
return 1;
}
printf("Good: wait seems to be correctly interrupted by signals\n");
return 0;
}