Skip to content

Commit daf865e

Browse files
authored
Handle waitpid race condition when SIGCHLD is set to SIG_IGN (#57241)
The `fork()` we do here relies on `SIGCHLD` to make sure that we don't race against the child. This is easy to see in an embedding application that dynamically links `libjulia`: ```c int main(int argc, char *argv[]) { signal(SIGCHLD, SIG_IGN); void *handle = dlopen("path/to/libjulia.so", RTLD_LAZY); return 0; } ``` Without this change, this fails with an error message: ``` Error during libstdcxxprobe in parent process: waitpid: No child processes ``` Resolves #57240
1 parent a52de83 commit daf865e

File tree

3 files changed

+32
-6
lines changed

3 files changed

+32
-6
lines changed

cli/loader_lib.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,10 +349,16 @@ static char *libstdcxxprobe(void)
349349
pid_t npid = waitpid(pid, &wstatus, 0);
350350
if (npid == -1) {
351351
if (errno == EINTR) continue;
352-
if (errno != EINTR) {
353-
perror("Error during libstdcxxprobe in parent process:\nwaitpid");
354-
exit(1);
352+
if (errno == ECHILD) {
353+
// SIGCHLD is set to SIG_IGN or has flag SA_NOCLDWAIT, so the child
354+
// did not become a zombie and wait for `waitpid` - it just exited.
355+
//
356+
// Assume that it exited successfully and use whatever libpath we
357+
// got out of the pipe, if any.
358+
break;
355359
}
360+
perror("Error during libstdcxxprobe in parent process:\nwaitpid");
361+
exit(1);
356362
}
357363
else if (!WIFEXITED(wstatus)) {
358364
const char *err_str = "Error during libstdcxxprobe in parent process:\n"

test/embedding/Makefile

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ EXE := $(suffix $(abspath $(JULIA)))
2121

2222
# get compiler and linker flags. (see: `contrib/julia-config.jl`)
2323
JULIA_CONFIG := $(JULIA) -e 'include(joinpath(Sys.BINDIR, Base.DATAROOTDIR, "julia", "julia-config.jl"))' --
24+
JULIA_LIBDIR := $(shell $(JULIA) -e 'println(joinpath(Sys.BINDIR, "..", "lib"))' --)
2425
CPPFLAGS_ADD :=
2526
CFLAGS_ADD = $(shell $(JULIA_CONFIG) --cflags)
2627
LDFLAGS_ADD = -lm $(shell $(JULIA_CONFIG) --ldflags --ldlibs)
@@ -29,23 +30,30 @@ DEBUGFLAGS += -g
2930

3031
#=============================================================================
3132

32-
release: $(BIN)/embedding$(EXE)
33-
debug: $(BIN)/embedding-debug$(EXE)
33+
release: $(BIN)/embedding$(EXE) $(BIN)/libdl-embedding$(EXE)
34+
debug: $(BIN)/embedding-debug$(EXE) $(BIN)/libdl-embedding$(EXE)
3435

3536
$(BIN)/embedding$(EXE): $(SRCDIR)/embedding.c
3637
$(CC) $^ -o $@ $(CPPFLAGS_ADD) $(CPPFLAGS) $(CFLAGS_ADD) $(CFLAGS) $(LDFLAGS_ADD) $(LDFLAGS)
3738

3839
$(BIN)/embedding-debug$(EXE): $(SRCDIR)/embedding.c
3940
$(CC) $^ -o $@ $(CPPFLAGS_ADD) $(CPPFLAGS) $(CFLAGS_ADD) $(CFLAGS) $(LDFLAGS_ADD) $(LDFLAGS) $(DEBUGFLAGS)
4041

42+
$(BIN)/libdl-embedding$(EXE): $(SRCDIR)/libdl_embedding.c
43+
$(CC) $^ -o $@ $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -ldl -DLIBJULIA_PATH=\"$(JULIA_LIBDIR)/libjulia.so\"
44+
45+
$(BIN)/libdl-embedding-debug$(EXE): $(SRCDIR)/libdl_embedding.c
46+
$(CC) $^ -o $@ $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(DEBUGFLAGS) -ldl -DLIBJULIA_PATH=\"$(JULIA_LIBDIR)/libjulia.so\"
47+
4148
ifneq ($(abspath $(BIN)),$(abspath $(SRCDIR)))
4249
# for demonstration purposes, our demo code is also installed
4350
# in $BIN, although this would likely not be typical
4451
$(BIN)/LocalModule.jl: $(SRCDIR)/LocalModule.jl
4552
cp $< $@
4653
endif
4754

48-
check: $(BIN)/embedding$(EXE) $(BIN)/LocalModule.jl
55+
check: $(BIN)/embedding$(EXE) $(BIN)/libdl-embedding$(EXE) $(BIN)/LocalModule.jl
56+
$(BIN)/libdl-embedding$(EXE) # run w/o error
4957
$(JULIA) --depwarn=error $(SRCDIR)/embedding-test.jl $<
5058
@echo SUCCESS
5159

test/embedding/libdl_embedding.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <dlfcn.h>
2+
#include <stdio.h>
3+
#include <signal.h>
4+
5+
int main(int argc, char *argv[])
6+
{
7+
// This test doesn't do much yet, except check
8+
// https://github.com/JuliaLang/julia/issues/57240
9+
signal(SIGCHLD, SIG_IGN);
10+
void *handle = dlopen(LIBJULIA_PATH, RTLD_LAZY);
11+
return 0;
12+
}

0 commit comments

Comments
 (0)