15dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes#include <unistd.h>
25dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes#include <sys/types.h>
35dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes#include <signal.h>
45dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes#include <sys/wait.h>
55dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes#include <stdio.h>
65dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes#include <string.h>
75dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes
85dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes/* Expected order is:
95dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes * Child signals parent
105dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes * Parent got signal
115dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes * Child will exit now
125dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes *
135dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes * The bug we test for: under strace -f, last two lines are swapped
145dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes * because wait syscall is suspended by strace and thus can't be interrupted.
155dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes */
165dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes
175dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughesstatic const char msg1[] = "Child signals parent\n";
185dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughesstatic const char msg2[] = "Parent got signal\n";
195dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughesstatic const char msg3[] = "Child will exit now\n";
205dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes
215dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughesstatic void handler(int s)
225dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes{
235dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	write(1, msg2, sizeof(msg2)-1);
245dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes}
255dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes
265dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughesstatic void test()
275dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes{
285dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	/* Note: in Linux, signal() installs handler with SA_RESTART flag,
295dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	 * therefore wait will be restarted.
305dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	 */
315dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	signal(SIGALRM, handler);
325dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes
335dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	if (fork() == 0) {
345dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		/* child */
355dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		sleep(1);
365dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		write(1, msg1, sizeof(msg1)-1);
375dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		kill(getppid(), SIGALRM);
385dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		sleep(1);
395dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		write(1, msg3, sizeof(msg3)-1);
405dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		_exit(0);
415dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	}
425dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes
435dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	/* parent */
445dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	wait(NULL);
455dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	_exit(0);
465dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes}
475dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes
485dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughesint main()
495dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes{
505dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	char buf1[80];
515dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	char buf2[80];
525dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	char buf3[80];
535dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	int pipefd[2];
545dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes
555dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	printf("Please run me under 'strace -f'\n");
565dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes
575dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	pipe(pipefd);
585dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes
595dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	if (fork() == 0) {
605dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		if (pipefd[1] != 1) {
615dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes			dup2(pipefd[1], 1);
625dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes			close(pipefd[1]);
635dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		}
645dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		test();
655dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	}
665dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes
675dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	if (pipefd[0] != 0) {
685dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		dup2(pipefd[0], 0);
695dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		close(pipefd[0]);
705dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	}
715dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	fgets(buf1, 80, stdin);	printf("%s", buf1);
725dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	fgets(buf2, 80, stdin);	printf("%s", buf2);
735dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	fgets(buf3, 80, stdin);	printf("%s", buf3);
745dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes
755dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	if (strcmp(buf1, msg1) != 0
765dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	 || strcmp(buf2, msg2) != 0
775dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	 || strcmp(buf3, msg3) != 0
785dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	) {
795dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		printf("ERROR! Expected order:\n%s%s%s", msg1, msg2, msg3);
805dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes		return 1;
815dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	}
825dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	printf("Good: wait seems to be correctly interrupted by signals\n");
835dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes	return 0;
845dec78d0c2663930cd1bbcecbbcee47f68bc52f3Elliott Hughes}
85