STC for fork SEGV after dlclose
David Rothenberger
daveroth@acm.org
Mon May 27 17:07:00 GMT 2013
The libapr1 test cases starting failing with my 64-bit package and
1.7.19-6. They worked fine with 1.7.19-5. After a little
investigation, I discovered that only the tests that involve fork()
were failing and only if the "testdso" test case ran first. That
test case checks loading and unloading DLLs.
I extracted the attached STC. It creates a simple DLL and uses
dlopen() and dlclose() on it. Then it attempts a fork().
With the latest 32-bit snapshot (2013-05-24) this causes a
segfault. The same thing happens with the 64-bit release. With
1.7.18, the test case hangs for quite a while, but eventually
finishes, except that the fork() never really happens and I get a
weird error code when I run it in gdb. If I skip the dlclose() call,
the STC runs fine.
It's weird, but the libapr1 test suite does not fail on 32-bit with
the 2013-05-24 snapshot (or with 1.7.18). I don't know why the STC
fails and the test suite does not.
There's a pretty good chance that I'm doing something dumb in the
STC since I don't do this type of programming. If so, please let me
know and accept my apologies.
To run the test, just run "make". To run it without the dlclose(),
run "make test-nofail".
Regards,
David
--
David Rothenberger ---- daveroth@acm.org
alimony, n:
Having an ex you can bank on.
-------------- next part --------------
/***********************************************************************
* This is a STC to show that fork causes a SEGV after a DLL has been loaded
* and unloaded.
*
* It loads and unloads a test DLL then does a simple fork. This causes a SEGV
* with 1.7.19-6 (although not with 1.7.19-5). If the DLL is not unloaded then
* no SEGV occurs.
*
* This test was extracted from the APR test suite.
*
* To compile and run, just run make. To run the test without unloading the
* DLL, run "make test-nofail".
***********************************************************************/
#include <string.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
#include <errno.h>
#include <sys/wait.h>
int do_unload = 1;
void load_dso ()
{
char dll[PATH_MAX];
getcwd(dll, PATH_MAX);
strcat(dll, "/mod_test.dll");
void *os_handle = dlopen(dll, RTLD_NOW | RTLD_GLOBAL);
if (os_handle == NULL) {
perror("Could not open DLL");
exit(1);
}
if (do_unload) {
if (dlclose(os_handle) != 0) {
perror("Could not close DLL");
exit(1);
}
}
}
void do_fork ()
{
pid_t pid;
printf("Calling fork()\n"); fflush(stdout);
if ((pid = fork()) < 0) {
perror("fork failed");
exit(1);
}
else if (pid == 0) {
printf("In child\n"); fflush(stdout);
exit(0);
}
else {
printf("Awaiting child\n"); fflush(stdout);
// await child
int exit_int;
pid_t pstatus;
do {
pstatus = waitpid(pid, &exit_int, WUNTRACED);
} while (pstatus < 0 && errno == EINTR);
printf("Child finished\n"); fflush(stdout);
}
}
int main (int argc, const char * const * argv, const char * const *env)
{
if (argc > 1) {
do_unload = 0;
}
load_dso();
do_fork();
return 0;
}
-------------- next part --------------
int count_reps(int reps);
int count_reps(int reps)
{
int i = 0;
for (i = 0;i < reps; i++);
return i;
}
-------------- next part --------------
CC=gcc
CFLAGS=-Wall
STC=stc_dso_breaks_fork
LIBS=-ldl
.PHONY: test test-nofail
test: $(STC) mod_test.dll
./$(STC)
test-nofail: $(STC) mod_test.dll
./$(STC) no-fail
$(STC): $(STC).c
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
mod_test.dll: mod_test.o
$(CC) -shared -o $@ $^
mod_test.o: mod_test.c
$(CC) $(CFLAGS) -c $^
.PHONY: clean
clean:
rm -f $(STC) mod_test.o mod_test.dll $(STC).exe.stackdump
-------------- next part --------------
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
More information about the Cygwin
mailing list