diff options
-rw-r--r-- | .editorconfig | 2 | ||||
-rw-r--r-- | lib9p/CMakeLists.txt | 4 | ||||
-rwxr-xr-x | lib9p/tests/runtest | 45 | ||||
-rw-r--r-- | lib9p/tests/test_server/main.c | 4 | ||||
-rw-r--r-- | libcr/coroutine.c | 23 | ||||
-rw-r--r-- | libcr_ipc/include/libcr_ipc/rpc.h | 6 | ||||
-rw-r--r-- | libhw/host_net.c | 4 |
7 files changed, 77 insertions, 11 deletions
diff --git a/.editorconfig b/.editorconfig index 88ea6cb..8fb3a6f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -33,7 +33,7 @@ _mode = 9p [{lib9p/tests/test_server/static.h.gen,build-aux/embed-sources.h.gen}] _mode = sh -[{build-aux/linux-errno.txt.gen,libusb/include/libusb/tusb_helpers.h.gen}] +[{build-aux/linux-errno.txt.gen,libusb/include/libusb/tusb_helpers.h.gen,lib9p/tests/runtest}] _mode = bash [{lib9p/idl.gen,lib9p/include/lib9p/linux-errno.h.gen,build-aux/stack.c.gen}] diff --git a/lib9p/CMakeLists.txt b/lib9p/CMakeLists.txt index 86fde39..2f5fc70 100644 --- a/lib9p/CMakeLists.txt +++ b/lib9p/CMakeLists.txt @@ -18,4 +18,8 @@ target_link_libraries(lib9p INTERFACE if (ENABLE_TESTS) add_subdirectory(tests/test_server) + add_test( + NAME "lib9p/runtest" + COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/runtest" + ) endif() diff --git a/lib9p/tests/runtest b/lib9p/tests/runtest new file mode 100755 index 0000000..29d2089 --- /dev/null +++ b/lib9p/tests/runtest @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# lib9p/tests/runtest - TODO +# +# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later + +set -euE -o pipefail +set -x + +valgrind --error-exitcode=2 ./tests/test_server/test_server & +server_pid=$! +# shellcheck disable=SC2064 +trap "kill $server_pid || true; wait $server_pid || true" EXIT +server_addr='localhost:9000' + +client=(9p -a "$server_addr") + +expect_lines() ( + { set +x; } &>/dev/null + printf >&2 '+ diff -u expected.txt actual.txt\n' + diff -u <(printf '%s\n' "$@") <(printf '%s\n' "$out") +) + +while [[ -d /proc/$server_pid && "$(readlink /proc/$server_pid/fd/4 2>/dev/null)" != socket:* ]]; do sleep 0.1; done + +out=$("${client[@]}" ls -l '') +expect_lines \ + 'd-r-xr-xr-x M 0 root root 0 Oct 7 15:51 Documentation' \ + '--r--r--r-- M 0 root root 14 Oct 7 15:51 README.md' + +out=$("${client[@]}" ls -l 'Documentation/') +expect_lines \ + '--r--r--r-- M 0 root root 4 Oct 7 15:51 x' + +out=$("${client[@]}" read 'README.md') +expect_lines \ + 'Hello, world!' + +out=$("${client[@]}" read 'Documentation/x') +expect_lines \ + 'foo' + +out=$("${client[@]}" stat 'Documentation/x') +expect_lines \ + "'x' 'root' 'root' 'root' q (0000000000000009 1 ) m 0444 at 1728337905 mt 1728337904 l 4 t 0 d 0" diff --git a/lib9p/tests/test_server/main.c b/lib9p/tests/test_server/main.c index adeba38..a6e4eeb 100644 --- a/lib9p/tests/test_server/main.c +++ b/lib9p/tests/test_server/main.c @@ -107,17 +107,17 @@ struct lib9p_srv srv = { static COROUTINE init_cr(void *) { cr_begin(); + sleep_for_ms(1); + for (int i = 0; i < CONFIG_SRV9P_NUM_CONNS; i++) { char name[] = {'r', 'e', 'a', 'd', '-', hexdig[i], '\0'}; if (!coroutine_add(name, read_cr, &srv)) error(1, 0, "coroutine_add(read_cr, &srv)"); - sleep_for_s(1); } for (int i = 0; i < 2*CONFIG_SRV9P_NUM_CONNS; i++) { char name[] = {'w', 'r', 'i', 't', 'e', '-', hexdig[i], '\0'}; if (!coroutine_add(name, lib9p_srv_write_cr, &srv)) error(1, 0, "coroutine_add(lib9p_srv_write_cr, &srv)"); - sleep_for_s(1); } cr_exit(); diff --git a/libcr/coroutine.c b/libcr/coroutine.c index 129f4da..73460b7 100644 --- a/libcr/coroutine.c +++ b/libcr/coroutine.c @@ -1,6 +1,6 @@ /* libcr/coroutine.c - Simple embeddable coroutine implementation * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ @@ -158,9 +158,19 @@ static_assert(CONFIG_COROUTINE_NUM > 1); #define _CR_SIG_GDB SIGWINCH #endif +#if CONFIG_COROUTINE_VALGRIND + /* Hack around a bug in Valgrind where it runs the + * sigsuspend(tmp_sigmask)-triggered handler function with the + * original mask, not the `tmp_mask`. */ + static bool _cr_plat_in_sigsuspend = false; +#endif + bool cr_plat_is_in_intrhandler(void) { +#if CONFIG_COROUTINE_VALGRIND + if (_cr_plat_in_sigsuspend) + return true; +#endif sigset_t cur_mask; - sigfillset(&cur_mask); sigprocmask(0, NULL, &cur_mask); if (sigismember(&cur_mask, _CR_SIG_SENTINEL)) /* Interrupts are disabled, so we cannot be in @@ -184,10 +194,13 @@ static_assert(CONFIG_COROUTINE_NUM > 1); assert(!_cr_plat_are_interrupts_enabled()); sigset_t set; sigemptyset(&set); +#if CONFIG_COROUTINE_VALGRIND + _cr_plat_in_sigsuspend = true; +#endif sigsuspend(&set); - - sigfillset(&set); - sigprocmask(SIG_SETMASK, &set, NULL); +#if CONFIG_COROUTINE_VALGRIND + _cr_plat_in_sigsuspend = false; +#endif } bool _cr_plat_save_and_disable_interrupts(void) { assert(!cr_plat_is_in_intrhandler()); diff --git a/libcr_ipc/include/libcr_ipc/rpc.h b/libcr_ipc/include/libcr_ipc/rpc.h index 0d6d25e..80eee74 100644 --- a/libcr_ipc/include/libcr_ipc/rpc.h +++ b/libcr_ipc/include/libcr_ipc/rpc.h @@ -1,6 +1,6 @@ /* libcr_ipc/rpc.h - Simple request/response system for libcr * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ @@ -120,8 +120,10 @@ .cid = cr_getcid(), \ }; \ _cr_ipc_sll_push_to_rear(&ch->waiting_reqs, &self); \ - if (ch->waiting_resps.front) \ + if (ch->waiting_resps.front) { \ cr_unpause(_cr_ipc_sll_node_cast(struct _##NAME##_waiting_resp, ch->waiting_resps.front)->cid); \ + _cr_ipc_sll_pop_from_front(&ch->waiting_resps); \ + } \ cr_pause_and_yield(); \ return resp; \ } \ diff --git a/libhw/host_net.c b/libhw/host_net.c index 917e764..d5a5ad5 100644 --- a/libhw/host_net.c +++ b/libhw/host_net.c @@ -1,6 +1,6 @@ /* libhw/host_net.c - <libhw/generic/net.h> implementation for hosted glibc * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ @@ -66,9 +66,11 @@ static void hostnet_init(void) { static inline bool RUN_PTHREAD(void *(*fn)(void *), void *args) { pthread_t thread; + bool saved = cr_save_and_disable_interrupts(); if (pthread_create(&thread, NULL, fn, args)) return true; cr_pause_and_yield(); + cr_restore_interrupts(saved); if (pthread_join(thread, NULL)) return true; return false; |