Beispiel #1
0
void
sigchld_handler(int signo)
{
	struct msqid_ds m_ds;
	int cstatus;

	/*
	 * Reap the child; if it exited successfully, then the test passed!
	 */
	if (waitpid(child_pid, &cstatus, 0) != child_pid)
		err(1, "waitpid");

	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 thus
	 * we should exit normally too.  First, tho, we print out
	 * the final stats for the message queue.
	 */

	if (msgctl(sender_msqid, IPC_STAT, &m_ds) == -1)
		err(1, "msgctl IPC_STAT");

	print_msqid_ds(&m_ds, 0600);

	exit(0);
}
Beispiel #2
0
int
main(int argc, char *argv[])
{
	struct sigaction sa;
	struct msqid_ds m_ds;
	struct test_mymsg m;
	sigset_t sigmask;

	if (argc != 2)
		usage();

	/*
	 * Install a SIGSYS handler so that we can exit gracefully if
	 * System V Message Queue 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");

	msgkey = 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_msqid = msgget(msgkey, IPC_CREAT | 0640)) == -1)
		err(1, "msgget");

	if (msgctl(sender_msqid, IPC_STAT, &m_ds) == -1)
		err(1, "msgctl IPC_STAT");

	print_msqid_ds(&m_ds, 0640);

	m_ds.msg_perm.mode = (m_ds.msg_perm.mode & ~0777) | 0600;

	if (msgctl(sender_msqid, IPC_SET, &m_ds) == -1)
		err(1, "msgctl IPC_SET");

	bzero(&m_ds, sizeof m_ds);

	if (msgctl(sender_msqid, IPC_STAT, &m_ds) == -1)
		err(1, "msgctl IPC_STAT");

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

	print_msqid_ds(&m_ds, 0600);

	switch ((child_pid = fork())) {
	case -1:
		err(1, "fork");
		/* NOTREACHED */

	case 0:
		receiver();
		break;

	default:
		break;
	}

	/*
	 * Send the first message to the receiver and wait for the ACK.
	 */
	m.mtype = MTYPE_1;
	strcpy(m.mtext, m1_str);
	if (msgsnd(sender_msqid, &m, strlen(m1_str) + 1, 0) == -1)
		err(1, "sender: msgsnd 1");

	if (msgrcv(sender_msqid, &m, sizeof(m.mtext), MTYPE_1_ACK, 0) !=
	    strlen(m1_str) + 1)
		err(1, "sender: msgrcv 1 ack");

	print_msqid_ds(&m_ds, 0600);

	/*
	 * Send the second message to the receiver and wait for the ACK.
	 */
	m.mtype = MTYPE_2;
	strcpy(m.mtext, m2_str);
	if (msgsnd(sender_msqid, &m, strlen(m2_str) + 1, 0) == -1)
		err(1, "sender: msgsnd 2");

	if (msgrcv(sender_msqid, &m, sizeof(m.mtext), MTYPE_2_ACK, 0) !=
	    strlen(m2_str) + 1)
		err(1, "sender: msgrcv 2 ack");

	/*
	 * Suspend forever; when we get SIGCHLD, the handler will exit.
	 */
	sigemptyset(&sigmask);
	(void) sigsuspend(&sigmask);

	/*
	 * ...and any other signal is an unexpected error.
	 */
	errx(1, "sender: received unexpected signal");
}
Beispiel #3
0
ATF_TC_BODY(msg, tc)
{
    struct sigaction sa;
    struct msqid_ds m_ds;
    struct mymsg m;
    sigset_t sigmask;
    int loop;
    int c_status;

    /*
     * Install a SIGSYS handler so that we can exit gracefully if
     * System V Message Queue 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);

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

    sender_msqid = msgget(msgkey, IPC_CREAT | 0640);
    ATF_REQUIRE_MSG(sender_msqid != -1, "msgget: %d", errno);

    if (did_sigsys) {
        atf_tc_skip("SYSV Message Queue not supported");
        return;
    }

    ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1,
                    "msgctl IPC_STAT 1: %d", errno);

    print_msqid_ds(&m_ds, 0640);

    m_ds.msg_perm.mode = (m_ds.msg_perm.mode & ~0777) | 0600;

    ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_SET, &m_ds) != -1,
                    "msgctl IPC_SET: %d", errno);

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

    ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds) != -1,
                    "msgctl IPC_STAT 2: %d", errno);

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

    print_msqid_ds(&m_ds, 0600);

    switch ((child_pid = fork())) {
    case -1:
        atf_tc_fail("fork: %d", errno);
        return;

    case 0:
        child_count++;
        receiver();
        break;

    default:
        break;
    }

    for (loop = 0; loop < maxloop; loop++) {
        /*
         * Send the first message to the receiver and wait for the ACK.
         */
        m.mtype = MTYPE_1;
        strcpy(m.mtext, m1_str);
        ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, sizeof(m), 0) != -1,
                        "sender: msgsnd 1: %d", errno);

        ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, sizeof(m),
                               MTYPE_1_ACK, 0) == sizeof(m),
                        "sender: msgrcv 1 ack: %d", errno);

        print_msqid_ds(&m_ds, 0600);

        /*
         * Send the second message to the receiver and wait for the ACK.
         */
        m.mtype = MTYPE_2;
        strcpy(m.mtext, m2_str);
        ATF_REQUIRE_MSG(msgsnd(sender_msqid, &m, sizeof(m), 0) != -1,
                        "sender: msgsnd 2: %d", errno);

        ATF_REQUIRE_MSG(msgrcv(sender_msqid, &m, sizeof(m),
                               MTYPE_2_ACK, 0) == sizeof(m),
                        "sender: msgrcv 2 ack: %d", errno);
    }

    /*
     * Wait for child to finish
     */
    sigemptyset(&sigmask);
    (void) sigsuspend(&sigmask);

    /*
     * ...and any other signal is an unexpected error.
     */
    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("child abnormal exit: %d", c_status);
        else if (WEXITSTATUS(c_status) != 0)
            atf_tc_fail("c status: %d", WEXITSTATUS(c_status));
        else {
            ATF_REQUIRE_MSG(msgctl(sender_msqid, IPC_STAT, &m_ds)
                            != -1, "msgctl IPC_STAT: %d", errno);

            print_msqid_ds(&m_ds, 0600);
            atf_tc_pass();
        }
    } else
        atf_tc_fail("sender: received unexpected signal");
}