Date: Thu, 10 Apr 2014 15:07:04 GMT From: Alex Crichton <acrichton@mozilla.com> To: freebsd-gnats-submit@FreeBSD.org Subject: misc/188425: Frequent segfault with multithreaded fork Message-ID: <201404101507.s3AF7476041659@cgiserv.freebsd.org> Resent-Message-ID: <201404101510.s3AFA1dB016300@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 188425
>Category: misc
>Synopsis: Frequent segfault with multithreaded fork
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Thu Apr 10 15:10:01 UTC 2014
>Closed-Date:
>Last-Modified:
>Originator: Alex Crichton
>Release: 10.0-RELEASE-p1
>Organization:
Mozilla
>Environment:
FreeBSD freebsd-vm 10.0-RELEASE-p1 FreeBSD 10.0-RELEASE-p1 #0: Tue Apr 8 06:45:06 UTC 2014 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64
>Description:
Recently we've found that FreeBSD is segfaulting or hanging frequently when dealing with what we suspect is a multithreaded forking situation. I've written a small program (attached) which exhibits the bug. This program will segfault or trip an assertion in libthr frequently, but not always.
>How-To-Repeat:
1. Download attached bug.c
2. clang -o bug bug.c -lthr
3. Run the program repeatedly until it segfaults, normally requiring less than 500 runs.
When running the program, I've been using this script:
for i in {1..1000}; do; echo $i; ./bug || break; done
>Fix:
Patch attached with submission follows:
#include <assert.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
static pthread_mutex_t lock;
static pthread_cond_t cond;
static volatile int cnt = 0;
static void test() {
int p = fork();
assert(p >= 0);
if (p == 0) {
_exit(0);
}
int a = 1;
assert(waitpid(p, &a, 0) == p);
assert(WEXITSTATUS(a) == 0);
}
static void *child(void *arg) {
test();
assert(pthread_mutex_lock(&lock) == 0);
cnt -= 1;
if (cnt == 0) {
assert(pthread_cond_signal(&cond) == 0);
}
assert(pthread_mutex_unlock(&lock) == 0);
return arg;
}
int main() {
assert(pthread_mutex_init(&lock, NULL) == 0);
assert(pthread_cond_init(&cond, NULL) == 0);
pthread_t c1, c2;
cnt = 2;
assert(pthread_create(&c1, NULL, child, NULL) == 0);
assert(pthread_create(&c2, NULL, child, NULL) == 0);
assert(pthread_mutex_lock(&lock) == 0);
while (cnt != 0) {
assert(pthread_cond_wait(&cond, &lock) == 0);
}
assert(pthread_mutex_unlock(&lock) == 0);
pthread_join(c1, NULL);
pthread_join(c2, NULL);
}
>Release-Note:
>Audit-Trail:
>Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201404101507.s3AF7476041659>
