From 802f5e4d6926f0be9294d71c6cadcbe872dbddf2 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Tue, 13 Oct 2026 11:40:22 -0600 Subject: [PATCH] ggate: fix test intermittency * ggatel: fix piped output. Flush stdout before daemonizing, so the output can be read when it's in a command pipeline. * ggated: bind the port _before_ daemonizing, so an invoking script can be sure that the port is bound as soon as the command returns. * tests: allow ggatec or ggatel to automatically allocate a device number instead of choosing one in a racy way. With all of these changes I can no run the tests 1000 times without fail. And in parallel, too. MFC after: 1 week Sponsored by: ConnectWise PR: 298942 Reported by: siva Reviewed by: ngie Differential Revision: https://reviews.freebsd.org/D60707 --- sbin/ggate/ggated/ggated.c | 21 ++++++----- sbin/ggate/ggatel/ggatel.c | 4 ++- tests/sys/geom/class/gate/Makefile | 3 -- tests/sys/geom/class/gate/ggate_test.sh | 48 +++++++++---------------- 4 files changed, 33 insertions(+), 43 deletions(-) diff --git a/sbin/ggate/ggated/ggated.c b/sbin/ggate/ggated/ggated.c index ef7b61cb13c4..dd6c53c80ccf 100644 --- a/sbin/ggate/ggated/ggated.c +++ b/sbin/ggate/ggated/ggated.c @@ -1100,14 +1100,6 @@ main(int argc, char *argv[]) err(EXIT_FAILURE, "Cannot open/create pidfile"); } - if (!g_gate_verbose) { - /* Run in daemon mode. */ - if (daemon(0, 0) == -1) - g_gate_xlog("Cannot daemonize: %s", strerror(errno)); - } - - pidfile_write(pfh); - signal(SIGCHLD, SIG_IGN); sfd = socket(AF_INET, SOCK_STREAM, 0); @@ -1129,6 +1121,19 @@ main(int argc, char *argv[]) signal(SIGHUP, huphandler); + if (!g_gate_verbose) { + /* + * Run in daemon mode. Daemonize _after_ opening the socket, + * so consumers may connect as soon as the ggated command + * returns, but _before_ writing the pidfile, because daemon() + * changes the pid. + */ + if (daemon(0, 0) == -1) + g_gate_xlog("Cannot daemonize: %s", strerror(errno)); + } + + pidfile_write(pfh); + for (;;) { fromlen = sizeof(from); tmpsfd = accept(sfd, &from, &fromlen); diff --git a/sbin/ggate/ggatel/ggatel.c b/sbin/ggate/ggatel/ggatel.c index 1cbb6af28b7e..cafa6a385457 100644 --- a/sbin/ggate/ggatel/ggatel.c +++ b/sbin/ggate/ggatel/ggatel.c @@ -191,8 +191,10 @@ g_gatel_create(void) ggioc.gctl_maxcount = 0; strlcpy(ggioc.gctl_info, path, sizeof(ggioc.gctl_info)); g_gate_ioctl(G_GATE_CMD_CREATE, &ggioc); - if (unit == -1) + if (unit == -1) { printf("%s%u\n", G_GATE_PROVIDER_NAME, ggioc.gctl_unit); + fflush(stdout); + } unit = ggioc.gctl_unit; g_gatel_serve(fd); } diff --git a/tests/sys/geom/class/gate/Makefile b/tests/sys/geom/class/gate/Makefile index 5ebc1d9304e0..8ecb2e1a3751 100644 --- a/tests/sys/geom/class/gate/Makefile +++ b/tests/sys/geom/class/gate/Makefile @@ -4,7 +4,4 @@ TESTSDIR= ${TESTSBASE}/sys/geom/class/${.CURDIR:T} ATF_TESTS_SH+= ggate_test -# Tests listen on the same port. -TEST_METADATA.ggate_test+= is_exclusive=true - .include diff --git a/tests/sys/geom/class/gate/ggate_test.sh b/tests/sys/geom/class/gate/ggate_test.sh index 4cbc5d80ae89..398d5bee6d80 100644 --- a/tests/sys/geom/class/gate/ggate_test.sh +++ b/tests/sys/geom/class/gate/ggate_test.sh @@ -16,14 +16,14 @@ ggatec_trim_body() load_ggate port=33080 - us=$(alloc_ggate_dev) work=$(alloc_md) atf_check -e ignore -o ignore dd if=/dev/random of=/dev/$work bs=1m count=1 conv=notrunc echo $CONF >> $PLAINFILES echo "localhost RW /dev/$work" > $CONF atf_check ggated -p $port -F $PIDFILE $CONF - atf_check ggatec create -p $port -u $us localhost /dev/$work - ggate_dev=/dev/ggate${us} + atf_check -o save:ggateu ggatec create -p $port localhost /dev/$work + ggate_dev=/dev/`cat ggateu` + cat ggateu | sed 's:ggate::' >> ggate.devs wait_for_ggate_device ${ggate_dev} # ggatec only supports read or write. @@ -55,7 +55,6 @@ ggated_body() load_ggate port=33081 - us=$(alloc_ggate_dev) work=$(alloc_md) src=$(alloc_md) @@ -68,16 +67,16 @@ ggated_body() echo "127.0.0.1 RW /dev/$work" > $CONF atf_check ggated -p $port -F $PIDFILE $CONF - atf_check ggatec create -p $port -u $us 127.0.0.1 /dev/$work - - ggate_dev=/dev/ggate${us} + atf_check -o save:ggateu ggatec create -p $port 127.0.0.1 /dev/$work + ggate_dev=/dev/`cat ggateu` + cat ggateu | sed 's:ggate::' >> ggate.devs wait_for_ggate_device ${ggate_dev} atf_check -e ignore -o ignore \ dd if=/dev/${src} of=${ggate_dev} bs=1m count=1 conv=notrunc - checksum /dev/$src /dev/$work + checksum /dev/$src /dev/$work $ggate_dev } ggated_cleanup() @@ -98,22 +97,21 @@ ggatel_file_body() { load_ggate - us=$(alloc_ggate_dev) echo src work >> ${PLAINFILES} dd if=/dev/random of=work bs=1m count=1 dd if=/dev/random of=src bs=1m count=1 - atf_check ggatel create -u $us work - - ggate_dev=/dev/ggate${us} + atf_check -o save:ggateu ggatel create work + ggate_dev=/dev/`cat ggateu` + cat ggateu | sed 's:ggate::' >> ggate.devs wait_for_ggate_device ${ggate_dev} atf_check -e ignore -o ignore \ dd if=src of=${ggate_dev} bs=1m count=1 conv=notrunc - checksum src work + checksum src work $ggate_dev } ggatel_file_cleanup() @@ -134,7 +132,6 @@ ggatel_md_body() { load_ggate - us=$(alloc_ggate_dev) work=$(alloc_md) src=$(alloc_md) @@ -143,16 +140,16 @@ ggatel_md_body() atf_check -e ignore -o ignore \ dd if=/dev/random of=$src bs=1m count=1 conv=notrunc - atf_check ggatel create -u $us /dev/$work - - ggate_dev=/dev/ggate${us} + atf_check -o save:ggateu ggatel create /dev/$work + ggate_dev=/dev/`cat ggateu` + cat ggateu | sed 's:ggate::' >> ggate.devs wait_for_ggate_device ${ggate_dev} atf_check -e ignore -o ignore \ dd if=/dev/$src of=${ggate_dev} bs=1m count=1 conv=notrunc - checksum /dev/$src /dev/$work + checksum /dev/$src /dev/$work $ggate_dev } ggatel_md_cleanup() @@ -168,18 +165,6 @@ atf_init_test_cases() atf_add_test_case ggatec_trim } -alloc_ggate_dev() -{ - local us - - us=0 - while [ -c /dev/ggate${us} ]; do - : $(( us += 1 )) - done - echo ${us} > ggate.devs - echo ${us} -} - alloc_md() { local md @@ -195,6 +180,7 @@ checksum() local src work src=$1 work=$2 + ggate_dev=$3 src_checksum=$(md5 -q $src) work_checksum=$(md5 -q $work) @@ -203,7 +189,7 @@ checksum() atf_fail "work md5 checksum didn't match" fi - ggate_checksum=$(md5 -q /dev/ggate${us}) + ggate_checksum=$(md5 -q $ggate_dev) if [ "$ggate_checksum" != "$src_checksum" ]; then atf_fail "ggate md5 checksum didn't match" fi