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