diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 58e806ec..feb0e727 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -281,10 +281,10 @@ jobs: make -C test/bsd shm_tap_bridge test/bsd/shm_tap_bridge & sleep 2 - set -o pipefail; make -C test/bsd CC=${{ matrix.cc }} | tee log + make -C test/bsd CC=${{ matrix.cc }} > log - if: success() || failure() run: | - # cat log + cat log test/health.awk < log > json scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/bsd_${{ matrix.cc }}_$(date +"%Y%m%d").json" diff --git a/mongoose.c b/mongoose.c index ad9a2f16..d61a5e4e 100644 --- a/mongoose.c +++ b/mongoose.c @@ -294,7 +294,8 @@ int listen(int fd, int backlog) { int accept(int fd, struct sockaddr *addr, socklen_t *addrlen) { struct mg_bsd_sock *ls = get(fd); if (!ls) return -1; - struct sockaddr_in peer = {0}; + struct sockaddr_in peer; + memset(&peer, 0, sizeof(peer)); void *t = mg_bsd_transport_accept(ls->t, &peer, ls->nonblock); if (!t) return -1; // errno was set by transport_accept() struct mg_bsd_sock *ns = (struct mg_bsd_sock *) calloc(1, sizeof(*ns)); @@ -417,7 +418,8 @@ void freeaddrinfo(struct addrinfo *res) { (void) res; } #endif int inet_pton(int af, const char *src, void *dst) { - struct mg_addr a = {0}; + struct mg_addr a; + memset(&a, 0, sizeof(a)); if (af == AF_INET && mg_aton(mg_str_s(src), &a)) { memcpy(dst, &a.addr.ip4, 4); return 1; } return 0; } @@ -432,7 +434,8 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { } in_addr_t inet_addr(const char *cp) { - struct mg_addr a = {0}; + struct mg_addr a; + memset(&a, 0, sizeof(a)); return mg_aton(mg_str_s(cp), &a) ? a.addr.ip4 : (in_addr_t) -1; } diff --git a/src/bsd.c b/src/bsd.c index 9903c169..b1f41358 100644 --- a/src/bsd.c +++ b/src/bsd.c @@ -127,7 +127,8 @@ int listen(int fd, int backlog) { int accept(int fd, struct sockaddr *addr, socklen_t *addrlen) { struct mg_bsd_sock *ls = get(fd); if (!ls) return -1; - struct sockaddr_in peer = {0}; + struct sockaddr_in peer; + memset(&peer, 0, sizeof(peer)); void *t = mg_bsd_transport_accept(ls->t, &peer, ls->nonblock); if (!t) return -1; // errno was set by transport_accept() struct mg_bsd_sock *ns = (struct mg_bsd_sock *) calloc(1, sizeof(*ns)); @@ -250,7 +251,8 @@ void freeaddrinfo(struct addrinfo *res) { (void) res; } #endif int inet_pton(int af, const char *src, void *dst) { - struct mg_addr a = {0}; + struct mg_addr a; + memset(&a, 0, sizeof(a)); if (af == AF_INET && mg_aton(mg_str_s(src), &a)) { memcpy(dst, &a.addr.ip4, 4); return 1; } return 0; } @@ -265,7 +267,8 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { } in_addr_t inet_addr(const char *cp) { - struct mg_addr a = {0}; + struct mg_addr a; + memset(&a, 0, sizeof(a)); return mg_aton(mg_str_s(cp), &a) ? a.addr.ip4 : (in_addr_t) -1; } diff --git a/test/bsd/Makefile b/test/bsd/Makefile index 7be18f2a..062bbe2a 100644 --- a/test/bsd/Makefile +++ b/test/bsd/Makefile @@ -15,15 +15,25 @@ endif .PHONY: all bsd_test bsd_client shm_tap_bridge shm_port_bridge bsd_s390 clean -SOURCES = bsd_shm_test.c ../../mongoose.c - -# FreeRTOS -SOURCES += FreeRTOS-Kernel/portable/MemMang/heap_4.c -SOURCES += FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/port.c -SOURCES += FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c +TEST_SOURCES = bsd_shm_test.c +# A C++ application compiles its sources as C++, linking Mongoose and FreeRTOS as C. +# FreeRTOS does not build as C++, so C sources are compiled separately. +C_SOURCES = ../../mongoose.c +C_SOURCES += FreeRTOS-Kernel/portable/MemMang/heap_4.c +C_SOURCES += FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/port.c +C_SOURCES += FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c +C_SOURCES += $(wildcard FreeRTOS-Kernel/*.c) +C_OBJECTS = $(notdir $(C_SOURCES:.c=.o)) +C_INPUTS = $(foreach S,$(C_SOURCES),-x c $(S)) CFLAGS += -IFreeRTOS-Kernel/include CFLAGS += -IFreeRTOS-Kernel/portable/ThirdParty/GCC/Posix -Wno-conversion -Wno-undef +ifeq "$(findstring ++,$(CC))" "" +TEST_LANGUAGE = c +else +TEST_LANGUAGE = c++ +endif + DOCKER_BIN ?= docker CWD ?= $(realpath $(CURDIR)) ROOT_DIR = $(realpath $(CWD)/../..) @@ -38,8 +48,10 @@ all bsd: shm_tap_bridge bsd_client FreeRTOS-Kernel bsd_test ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./bsd_test $(ARGS) # requires shm_tap_bridge to be running -bsd_test: $(SOURCES) bsd_x_test.c ../../mongoose.h shm_queue.h - $(CC) $(SOURCES) $(wildcard FreeRTOS-Kernel/*.c) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) -o $@ +bsd_test: FreeRTOS-Kernel + $(CC) $(C_INPUTS) -c $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) + $(CC) -x $(TEST_LANGUAGE) -c $(TEST_SOURCES) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) + $(CC) $(C_OBJECTS) $(TEST_SOURCES:.c=.o) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) -o $@ bsd_client: bsd_client.c $(CC) bsd_client.c -pthread -o $@ diff --git a/test/bsd/bsd_client.c b/test/bsd/bsd_client.c index 0fb1a1a8..8a6b81ef 100644 --- a/test/bsd/bsd_client.c +++ b/test/bsd/bsd_client.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #define PORT 1234 @@ -46,6 +47,7 @@ static void *worker(void *arg) { const char *host = (const char *) arg; char tx[DATA_SIZE], rx[DATA_SIZE]; struct sockaddr_in sa; + struct timeval timeout; unsigned port = 0; int fd; @@ -54,6 +56,11 @@ static void *worker(void *arg) { fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) goto fail; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) != 0 || + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) != 0) + goto fail_close; memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; diff --git a/test/bsd/bsd_x_test.c b/test/bsd/bsd_x_test.c index 8f911fe7..74395a45 100644 --- a/test/bsd/bsd_x_test.c +++ b/test/bsd/bsd_x_test.c @@ -42,7 +42,10 @@ static void client_task(void *args) { struct client_data *d = (struct client_data *) args; char req[256]; fd = socket(AF_INET, SOCK_STREAM, 0); - struct sockaddr_in sa = {.sin_family = AF_INET, .sin_port = htons(80)}; + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons(80); memcpy(&sa.sin_addr, &d->ip, 4); c = connect(fd, (struct sockaddr *) &sa, sizeof(sa)); ASSERT(c >= 0); @@ -73,6 +76,7 @@ static void echo_task(void *args) { char buf[512]; size_t i = 0; ssize_t n; + MG_INFO(("Echo task started: %d", fd)); while ((n = recv(fd, buf, sizes[i++ % (sizeof(sizes) / sizeof(sizes[0]))], 0)) > 0) send(fd, buf, (size_t) n, 0); close(fd); @@ -82,9 +86,14 @@ static void echo_task(void *args) { // accept loop. Waits for incoming connections on port 1234 and spawns // an echo_task for each one, allowing concurrent clients. static void atask(void *args) { + BaseType_t result; mg_bsd_init(); int lfd = socket(AF_INET, SOCK_STREAM, 0); - struct sockaddr_in sa = {.sin_family = AF_INET, .sin_port = htons(1234), .sin_addr = {INADDR_ANY}}; + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons(1234); + sa.sin_addr.s_addr = INADDR_ANY; bind(lfd, (struct sockaddr *) &sa, sizeof(sa)); listen(lfd, 5); fcntl(lfd, F_SETFL, O_NONBLOCK); @@ -93,7 +102,10 @@ static void atask(void *args) { int fd = accept(lfd, NULL, NULL); if (fd < 0) { vTaskDelay(pdMS_TO_TICKS(10)); continue; } // echo_task at higher priority than task1 - xTaskCreate(echo_task, "echo", 512, (void *) (uintptr_t) fd, configMAX_PRIORITIES - 1, NULL); + result = xTaskCreate(echo_task, "echo", 512, (void *) (uintptr_t) fd, + configMAX_PRIORITIES - 1, NULL); + MG_INFO(("Echo task %d: %s", fd, result == pdPASS ? "created" : "FAILED")); + ASSERT(result == pdPASS); } close(lfd); s_wait = false; @@ -118,7 +130,7 @@ static void task2(void *args) { // atask at higher priority than task1 xTaskCreate(atask, "atask", 256, NULL, configMAX_PRIORITIES - 1, NULL); ip = mg_mprintf("%M", mg_print_ip4, &mgr->ifp->ip); - cmd[0] = "./bsd_client"; + cmd[0] = (char *) "./bsd_client"; cmd[1] = ip; cmd[2] = NULL; ASSERT(posix_spawn(&pid, cmd[0], NULL, NULL, cmd, environ) == 0); @@ -217,6 +229,7 @@ static void task1(void *args) { while (!s_done) { mg_mgr_poll(mgr, 0); mg_bsd_poll(mgr); + vTaskDelay(1); // Let idle reclaim deleted echo tasks } s_done = false; vTaskDelete(NULL);