diff options
| author | thorpej <thorpej@NetBSD.org> | 2021-10-10 17:43:15 +0000 |
|---|---|---|
| committer | thorpej <thorpej@NetBSD.org> | 2021-10-10 17:43:15 +0000 |
| commit | 3008191c81ac7be41756e146ef958c5a24e8a0b6 (patch) | |
| tree | 3a34cc9f1ec2eaeb9052146999ef26479c4df3d4 /tests/kernel/kqueue | |
| parent | bb99a516df40917d80571f37761bca74e299f00c (diff) | |
Add a test case to heavily exercise EVFILT_PROC + NOTE_TRACK.
Diffstat (limited to 'tests/kernel/kqueue')
| -rw-r--r-- | tests/kernel/kqueue/t_proc4.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/tests/kernel/kqueue/t_proc4.c b/tests/kernel/kqueue/t_proc4.c new file mode 100644 index 00000000000..d5eb6d3e4a3 --- /dev/null +++ b/tests/kernel/kqueue/t_proc4.c @@ -0,0 +1,170 @@ +/* $NetBSD: t_proc4.c,v 1.1 2021/10/10 17:43:15 thorpej Exp $ */ + +/*- + * Copyright (c) 2021 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_proc4.c,v 1.1 2021/10/10 17:43:15 thorpej Exp $"); + +#include <sys/event.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include <err.h> +#include <limits.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <atf-c.h> + +/* 10 children each create 10 grandchildren. */ +#define TOTAL_CHILDREN 10 +#define TOTAL_GRANDCHILDREN (TOTAL_CHILDREN * TOTAL_CHILDREN) +#define TOTAL_DESCENDENTS (TOTAL_CHILDREN + TOTAL_GRANDCHILDREN) + +#define EXIT_CHILD 66 +#define EXIT_GRANDCHILD 76 + +static void +child(void) +{ + int i, status; + pid_t pid; + + for (i = 0; i < TOTAL_CHILDREN; i++) { + ATF_REQUIRE((pid = fork()) != -1); + if (pid == 0) { + /* grandchild */ + _exit(EXIT_GRANDCHILD); + } + } + + for (i = 0; i < TOTAL_CHILDREN; i++) { + ATF_REQUIRE((pid = wait(&status)) != -1); + } + _exit(EXIT_CHILD); +} + +ATF_TC(proc4); +ATF_TC_HEAD(proc4, tc) +{ + atf_tc_set_md_var(tc, "descr", "Exercises EVFILT_PROC + NOTE_TRACK"); +} + +ATF_TC_BODY(proc4, tc) +{ + int total_tracks = 0; + int child_exits = 0; + int grandchild_exits = 0; + pid_t pid; + int kq, status; + struct kevent event; + struct timespec ts = { 0, 0 }; + int i, rv; + + ATF_REQUIRE((kq = kqueue()) >= 0); + + EV_SET(&event, getpid(), EVFILT_PROC, EV_ADD, + NOTE_TRACK | NOTE_EXIT, 0, 0); + + ATF_REQUIRE(kevent(kq, &event, 1, NULL, 0, NULL) == 0); + + for (i = 0; i < TOTAL_CHILDREN; i++) { + ATF_REQUIRE((pid = fork()) != -1); + if (pid == 0) { + child(); + /* NOTREACHED */ + } + } + + for (;;) { + if (total_tracks == TOTAL_DESCENDENTS && + child_exits == TOTAL_CHILDREN && + grandchild_exits == TOTAL_GRANDCHILDREN) { + break; + } + memset(&event, 0, sizeof(event)); + rv = kevent(kq, NULL, 0, &event, 1, NULL); + ATF_REQUIRE(rv != -1); + ATF_REQUIRE(rv == 1); + if (event.fflags & NOTE_CHILD) { + total_tracks++; + ATF_REQUIRE(total_tracks <= TOTAL_DESCENDENTS); + } else if (event.fflags & NOTE_EXIT) { + ATF_REQUIRE(event.flags & EV_EOF); + ATF_REQUIRE(event.data >= 0); + ATF_REQUIRE(event.data <= UINT_MAX); + status = (int)event.data; + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE(WEXITSTATUS(status) == EXIT_CHILD || + WEXITSTATUS(status) == EXIT_GRANDCHILD); + if (WEXITSTATUS(status) == EXIT_CHILD) { + child_exits++; + ATF_REQUIRE(child_exits <= TOTAL_CHILDREN); + ATF_REQUIRE(wait4((pid_t)event.ident, + &status, + WNOHANG, + NULL) != -1); + ATF_REQUIRE(status == (int)event.data); + } else { + grandchild_exits++; + ATF_REQUIRE(grandchild_exits <= + TOTAL_GRANDCHILDREN); + } + } else { + /* + * We didn't ask for NOTE_FORK, so we don't + * expect to ever see it, even though we are + * getting NOTE_CHILD as the result of the + * NOTE_TRACK. + */ + ATF_REQUIRE((event.fflags & NOTE_FORK) == 0); + + /* + * Bomb out of we are getting a TRACKERR. + * XXX This could legitimately happen if + * the kernel is low on memory because the + * code path involved specifically chooses + * not to block when allocating memory. + */ + ATF_REQUIRE((event.fflags & NOTE_TRACKERR) == 0); + } + } + + ATF_REQUIRE(kevent(kq, NULL, 0, &event, 1, &ts) == 0); + + (void)close(kq); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, proc4); + + return atf_no_error(); +} |
