Beispiel #1
0
void
sigchld_handler(int signo)
{
	union semun sun;
	struct semid_ds s_ds;
	int cstatus;

	/*
	 * Reap the child; if it exited successfully, then we're on the
	 * right track!
	 */
	if (wait(&cstatus) == -1)
		err(1, "wait");

	if (WIFEXITED(cstatus) == 0)
		errx(1, "receiver exited abnormally");

	if (WEXITSTATUS(cstatus) != 0)
		errx(1, "receiver exited with status %d",
		    WEXITSTATUS(cstatus));

	/*
	 * If we get here, the child has exited normally, and we should
	 * decrement the child count.  If the child_count reaches 0, we
	 * should exit.
	 */

	sun.buf = &s_ds;
	if (semctl(sender_semid, 0, IPC_STAT, sun) == -1)
		err(1, "semctl IPC_STAT");

	print_semid_ds(&s_ds, 0600);

	if (--child_count != 0) {
		signal_was_sigchld = 1;
		return;
	}

	exit(0);
}
Beispiel #2
0
int
main(int argc, char *argv[])
{
	struct sigaction sa;
	union semun sun;
	struct semid_ds s_ds;
	sigset_t sigmask;
	int i;

	if (argc != 2)
		usage();

	/*
	 * Install a SIGSYS handler so that we can exit gracefully if
	 * System V Semaphore support isn't in the kernel.
	 */
	sa.sa_handler = sigsys_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	if (sigaction(SIGSYS, &sa, NULL) == -1)
		err(1, "sigaction SIGSYS");

	/*
	 * Install and SIGCHLD handler to deal with all possible exit
	 * conditions of the receiver.
	 */
	sa.sa_handler = sigchld_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	if (sigaction(SIGCHLD, &sa, NULL) == -1)
		err(1, "sigaction SIGCHLD");

	semkey = ftok(argv[1], 4160);

	/*
	 * Initialize child_pid to ourselves to that the cleanup function
	 * works before we create the receiver.
	 */
	child_pid = getpid();

	/*
	 * Make sure that when the sender exits, the message queue is
	 * removed.
	 */
	if (atexit(cleanup) == -1)
		err(1, "atexit");

	if ((sender_semid = semget(semkey, 1, IPC_CREAT | 0640)) == -1)
		err(1, "semget");

	
	sun.buf = &s_ds;
	if (semctl(sender_semid, 0, IPC_STAT, sun) == -1)
		err(1, "semctl IPC_STAT");

	print_semid_ds(&s_ds, 0640);

	s_ds.sem_perm.mode = (s_ds.sem_perm.mode & ~0777) | 0600;

	sun.buf = &s_ds;
	if (semctl(sender_semid, 0, IPC_SET, sun) == -1)
		err(1, "semctl IPC_SET");

	memset(&s_ds, 0, sizeof(s_ds));

	sun.buf = &s_ds;
	if (semctl(sender_semid, 0, IPC_STAT, sun) == -1)
		err(1, "semctl IPC_STAT");

	if ((s_ds.sem_perm.mode & 0777) != 0600)
		err(1, "IPC_SET of mode didn't hold");

	print_semid_ds(&s_ds, 0600);

	for (child_count = 0; child_count < 5; child_count++) {
		switch ((child_pid = fork())) {
		case -1:
			err(1, "fork");
			/* NOTREACHED */

		case 0:
			waiter();
			break;

		default:
			break;
		}
	}

	/*
	 * Wait for all of the waiters to be attempting to acquire the
	 * semaphore.
	 */
	for (;;) {
		i = semctl(sender_semid, 0, GETNCNT);
		if (i == -1)
			err(1, "semctl GETNCNT");
		if (i == 5)
			break;
	}

	/*
	 * Now set the thundering herd in motion by initializing the
	 * semaphore to the value 1.
	 */
	sun.val = 1;
	if (semctl(sender_semid, 0, SETVAL, sun) == -1)
		err(1, "sender: semctl SETVAL to 1");

	/*
	 * Suspend forever; when we get SIGCHLD, the handler will exit.
	 */
	sigemptyset(&sigmask);
	for (;;) {
		(void) sigsuspend(&sigmask);
		if (signal_was_sigchld)
			signal_was_sigchld = 0;
		else
			break;
	}

	/*
	 * ...and any other signal is an unexpected error.
	 */
	errx(1, "sender: received unexpected signal");
}
Beispiel #3
0
ATF_TC_BODY(sem, tc)
{
	struct sigaction sa;
	union semun sun;
	struct semid_ds s_ds;
	sigset_t sigmask;
	int sender_semid;
	int i;
	int c_status;

	/*
	 * Install a SIGSYS handler so that we can exit gracefully if
	 * System V Semaphore support isn't in the kernel.
	 */
	did_sigsys = 0;
	sa.sa_handler = sigsys_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	ATF_REQUIRE_MSG(sigaction(SIGSYS, &sa, NULL) != -1,
	    "sigaction SIGSYS: %d", errno);

	/*
	 * Install a SIGCHLD handler to deal with all possible exit
	 * conditions of the receiver.
	 */
	did_sigchild = 0;
	child_count = 0;
	sa.sa_handler = sigchld_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	ATF_REQUIRE_MSG(sigaction(SIGCHLD, &sa, NULL) != -1,
	    "sigaction SIGCHLD: %d", errno);

	semkey = get_ftok(4160);
	ATF_REQUIRE_MSG(semkey != (key_t)-1, "get_ftok failed");

	sender_semid = semget(semkey, 1, IPC_CREAT | 0640);
	ATF_REQUIRE_MSG(sender_semid != -1, "semget: %d", errno);
	write_int("sender_semid", sender_semid);

	if (did_sigsys) {
		atf_tc_skip("SYSV Semaphore not supported");
		return;
	}
	
	sun.buf = &s_ds;
	ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1,
	    "semctl IPC_STAT: %d", errno);

	print_semid_ds(&s_ds, 0640);

	s_ds.sem_perm.mode = (s_ds.sem_perm.mode & ~0777) | 0600;

	sun.buf = &s_ds;
	ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_SET, sun) != -1,
	    "semctl IPC_SET: %d", errno);

	memset(&s_ds, 0, sizeof(s_ds));

	sun.buf = &s_ds;
	ATF_REQUIRE_MSG(semctl(sender_semid, 0, IPC_STAT, sun) != -1,
	    "semctl IPC_STAT: %d", errno);

	ATF_REQUIRE_MSG((s_ds.sem_perm.mode & 0777) == 0600,
	    "IPC_SET of mode didn't hold");

	print_semid_ds(&s_ds, 0600);

	for (child_count = 0; child_count < 5; child_count++) {
		switch ((child_pid = fork())) {
		case -1:
			atf_tc_fail("fork: %d", errno);
			return;

		case 0:
			waiter();
			break;

		default:
			break;
		}
	}

	/*
	 * Wait for all of the waiters to be attempting to acquire the
	 * semaphore.
	 */
	for (;;) {
		i = semctl(sender_semid, 0, GETNCNT);
		if (i == -1)
			atf_tc_fail("semctl GETNCNT: %d", i);
		if (i == 5)
			break;
	}

	/*
	 * Now set the thundering herd in motion by initializing the
	 * semaphore to the value 1.
	 */
	sun.val = 1;
	ATF_REQUIRE_MSG(semctl(sender_semid, 0, SETVAL, sun) != -1,
	    "sender: semctl SETVAL to 1: %d", errno);

	/*
	 * Wait for all children to finish
	 */
	sigemptyset(&sigmask);
	for (;;) {
		(void) sigsuspend(&sigmask);
		if (did_sigchild) {
			c_status = child_status;
			if (c_status < 0)
				atf_tc_fail("waitpid: %d", -c_status);
			else if (WIFEXITED(c_status) == 0)
				atf_tc_fail("c abnormal exit: %d", c_status);
			else if (WEXITSTATUS(c_status) != 0)
				atf_tc_fail("c status: %d",
				    WEXITSTATUS(c_status));
			else {
				sun.buf = &s_ds;
				ATF_REQUIRE_MSG(semctl(sender_semid, 0,
						    IPC_STAT, sun) != -1,
				    "semctl IPC_STAT: %d", errno);

				print_semid_ds(&s_ds, 0600);
				atf_tc_pass();
			}
			if (child_count <= 0)
				break;
			did_sigchild = 0;
		} else {
			atf_tc_fail("sender: received unexpected signal");
			break;
		}
	}
}