Improve posix_spawn() some more

This commit is contained in:
Justine Tunney 2023-09-12 08:58:57 -07:00
parent 6430e474b4
commit 00084577a3
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
18 changed files with 301 additions and 293 deletions

View file

@ -180,6 +180,8 @@ int main(int argc, char *argv[]) {
_Exit(1);
}
__threaded = 1;
ASSERT_EQ(0, pthread_mutexattr_init(&attr));
ASSERT_EQ(0, pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL));
ASSERT_EQ(0, pthread_mutex_init(&mu, &attr));

View file

@ -23,8 +23,10 @@
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/rusage.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/safemacros.internal.h"
@ -219,6 +221,44 @@ TEST(posix_spawn, agony) {
}
}
void EmptySigHandler(int sig) {
}
TEST(posix_spawn, etxtbsy) {
if (IsWindows()) return; // can't deliver signals between processes
if (IsXnu()) return; // they don't appear impacted by this race condition
if (IsNetbsd()) return; // they don't appear impacted by this race condition
if (IsOpenbsd()) return; // they don't appear impacted by this race condition
int ws, me, pid, thief;
char *prog = "./life.com";
char *args[] = {prog, 0};
char *envs[] = {0};
sigset_t ss, old;
testlib_extract("/zip/life.com", prog, 0755);
for (int i = 0; i < 2; ++i) {
sigemptyset(&ss);
sigaddset(&ss, SIGUSR1);
sigprocmask(SIG_BLOCK, &ss, &old);
sigdelset(&ss, SIGUSR1);
ASSERT_SYS(0, 3, open(prog, O_RDWR));
signal(SIGUSR1, EmptySigHandler);
me = getpid();
if (!(thief = fork())) {
ASSERT_SYS(0, 0, kill(me, SIGUSR1));
ASSERT_SYS(EINTR, -1, sigsuspend(&ss));
_Exit(0);
}
EXPECT_SYS(0, 0, close(3));
EXPECT_SYS(EINTR, -1, sigsuspend(&ss));
EXPECT_EQ(ETXTBSY, posix_spawn(&pid, prog, NULL, NULL, args, envs));
EXPECT_EQ(0, kill(thief, SIGUSR1));
EXPECT_EQ(thief, wait(&ws));
ASSERT_EQ(0, ws);
sigprocmask(SIG_SETMASK, &old, 0);
unassert(!errno);
}
}
////////////////////////////////////////////////////////////////////////////////
void ForkExecveWait(const char *prog) {

View file

@ -100,16 +100,6 @@ o/$(MODE)/test/libc/stdio/posix_spawn_test.com.dbg: \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
o/$(MODE)/test/libc/stdio/wut_test.com.dbg: \
$(TEST_LIBC_STDIO_DEPS) \
o/$(MODE)/test/libc/stdio/wut_test.o \
o/$(MODE)/test/libc/stdio/stdio.pkg \
o/$(MODE)/tool/build/echo.com.zip.o \
$(LIBC_TESTMAIN) \
$(CRT) \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
$(TEST_LIBC_STDIO_OBJS): private \
DEFAULT_CCFLAGS += \
-fno-builtin

View file

@ -169,7 +169,7 @@ void *CondWaitDeferredWorker(void *arg) {
pthread_setcancelstate(PTHREAD_CANCEL_DEFERRED, 0);
ASSERT_EQ(0, pthread_mutex_lock(&mu));
ASSERT_EQ(ECANCELED, pthread_cond_timedwait(&cv, &mu, 0));
__builtin_trap();
abort();
}
TEST(pthread_cancel, condDeferredWait_reacquiresMutex) {

View file

@ -95,7 +95,7 @@ void *Worker(void *arg) {
sem_t **s = arg;
struct timespec ts;
ASSERT_SYS(0, 0, clock_gettime(CLOCK_REALTIME, &ts));
ts.tv_sec += 1;
ts.tv_sec += 10;
ASSERT_SYS(0, 0, sem_post(s[0]));
ASSERT_SYS(0, 0, sem_timedwait(s[1], &ts));
return 0;