Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Apr 2004 05:47:31 -0700 (PDT)
From:      Max Fomitchev <max.fomitchev@kaspersky.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   threads/65883: libkse's sigwait does not work after fork
Message-ID:  <200404221247.i3MClVLW013761@www.freebsd.org>
Resent-Message-ID: <200404221250.i3MCoLuK062517@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         65883
>Category:       threads
>Synopsis:       libkse's sigwait does not work after fork
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-threads
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Apr 22 05:50:21 PDT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Max Fomitchev
>Release:        5.1-RELEASE, 5.2-RELEASE, 5-CURRENT
>Organization:
Kaspersky Labs
>Environment:
FreeBSD freebsd-smtpgw.testlab2k.avp.ru 5.1-RELEASE FreeBSD 5.1-RELEASE #0: Thu Jun  5 02:55:42 GMT 2003     root@wv1u.btc.adaptec.com:/usr/obj/usr/src/sys/GENERIC  i386

>Description:
sigwait() call cannot receive a signal after fork() if the following code (simplified model of my current application) linked with libkse. This code works well with a various thread libraries (libc_r for example).
Another interesting feature, if you do not start threads explicitly at all, sigwait() will receive SIGINT from the scheduler(???) and the program exits.

//kse_test.c begin
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>

static pthread_mutex_t	m_lock;
static int ended;

static void *thr (void *arg)
{
  for (;;)
  {
    pthread_mutex_lock(&m_lock);
    if (ended == 1)
    {
      pthread_mutex_unlock(&m_lock);
      break;
    }
    pthread_mutex_unlock(&m_lock);
    sleep(1);
  }	

  return NULL;
}

static int dmn()
{
  switch (fork())
  {
    case 0: break;
    case -1: return -1;
    default: _exit(0);
  }

  if (setsid() < 0)
    return -1;

  switch (fork())
  {
    case 0: break;
    case -1: return -1;
    default: _exit(0);
  }

  return 0;
}

static int close_ios()
{
  int fd_l = 0;
  int fd = 0;

  errno = 0;
  chdir("/");
  fd_l = sysconf(_SC_OPEN_MAX);
  if ((fd_l < 0) || (errno != 0))
    return -1;

  for (fd = 0; fd < fd_l; fd++)
    close(fd);

  return 0;
}

static void signal_manager()
{
  int sign = 0;
  sigset_t sigs;

  sigemptyset(&sigs);
  sigaddset(&sigs, SIGINT); //exit
  sigprocmask(SIG_BLOCK, &sigs, NULL);

  for (;;)
  {
    sigwait(&sigs, &sign);

    switch (sign)
    {
      case SIGINT:
        pthread_mutex_lock(&m_lock);
        ended = 1;
        pthread_mutex_unlock(&m_lock);
        return;
      default: continue;
    }
  }
}

int main(int argc, const char *argv[])
{
  pthread_mutexattr_t mattr;
  pthread_attr_t pattr;
  pthread_t tid1, tid2;
  void *exit_status;

  ended = 0;
  if (dmn() != 0)
    return 10;

  if (close_ios() != 0)
    return 20;

  if ((pthread_attr_init(&pattr) != 0) ||
      (pthread_attr_setdetachstate(&pattr,
      PTHREAD_CREATE_JOINABLE) != 0)) 
    return 30;

  if ((pthread_mutexattr_init(&mattr) != 0) ||
      (pthread_mutex_init(&m_lock, &mattr) != 0))
    return 40;

  if (pthread_create(&tid1, &pattr, thr, NULL) != 0)
    return 51;
  if (pthread_create(&tid2, &pattr, thr, NULL) != 0)
    return 52;

  signal_manager();

  pthread_join(tid1, &exit_status);
  pthread_join(tid2, &exit_status);

  return 0;
}
//kse_test.c end

>How-To-Repeat:
bash-2.05b# gcc -v
Using built-in specs.
Configured with: FreeBSD/i386 system compiler
Thread model: posix
gcc version 3.2.2 [FreeBSD] 20030205 (release)
bash-2.05b# gcc kse_test.c -o kse_test -lc_r
bash-2.05b# ldd kse_test
kse_test:
        libc_r.so.5 => /usr/lib/libc_r.so.5 (0x2806b000)
        libc.so.5 => /usr/lib/libc.so.5 (0x2808e000)
bash-2.05b# ./kse_test; echo $?
0
bash-2.05b# ps -ax | grep kse_test
62277  ??  S      0:00.00 ./kse_test
bash-2.05b# kill -INT 62277
bash-2.05b# ps -ax | grep kse_test
bash-2.05b# gcc kse_test.c -o kse_test -lkse
bash-2.05b# ldd kse_test
kse_test:
        libkse.so.1 => /usr/lib/libkse.so.1 (0x2806b000)
        libc.so.5 => /usr/lib/libc.so.5 (0x2808b000)
bash-2.05b# ./kse_test; echo $?
0
bash-2.05b# ps -ax | grep kse_test
62288  ??  S      0:00.00 ./kse_test
bash-2.05b# kill -INT 62288
bash-2.05b# ps -ax | grep kse_test
62288  ??  R      0:00.00 ./kse_test
bash-2.05b# kill -9 62288
bash-2.05b# ps -ax | grep kse_test

>Fix:

>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200404221247.i3MClVLW013761>