Skip site navigation (1)Skip section navigation (2)
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>