threads/76694: fork cause hang in dup()/close() function in child
(-lc_r)
Serguei Leontiev
lse at CryptoPro.ru
Tue Jan 25 17:20:20 PST 2005
>Number: 76694
>Category: threads
>Synopsis: fork cause hang in dup()/close() function in child (-lc_r)
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-threads
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Jan 26 01:20:19 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Serguei Leontiev
>Release: 5.2.1
>Organization:
Crypto-Pro
>Environment:
FreeBSD build-fbsd 5.2.1-RELEASE FreeBSD 5.2.1-RELEASE #0: Mon Feb 23 20:45:55 GMT 2004 root at wv1u.btc.adaptec.com:/usr/obj/usr/src/sys/GENERIC i386
>Description:
For multithreaded application dup()/close() in other thread cause hang dup()/close() in child process after fork. Child do not use thread related operations.
This bug first detected for accept() library function after daemon(). May be daemon() not thread-safe, but dup()/close() - MUST thread-safe by POSIX, and MUST compatible with fork() anywhere.
This bug affected "-lc_r" library. Library "-lthr" & "-lkse" seems OK.
Sorry for my bests English.
>How-To-Repeat:
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
const int INFL = 1000000000;
const int PTHR = 4;
const int NATR = 2;
#ifndef SEMI_OK // if SEMI_OK not defined - >95% hang on my system
const int FRKL = 100;
const int CHLD = 100;
#else // if SEMI_OK defined - 50% hang on my system
const int FRKL = 10;
const int CHLD = 10;
#endif
void *test_write(void *pvcnt)
{
volatile sig_atomic_t *pscnt = (volatile sig_atomic_t *)pvcnt;
int n = *pscnt;
int i;
int fd;
for(i = 0; i < n; i++){
if(0 > (fd = dup(STDIN_FILENO))){
perror("dup:");
continue;
}
*pscnt = i;
if(0 > close(fd)){
perror("close:");
}
}
return NULL;
}
int main (void)
{
pthread_attr_t attrs[NATR];
pthread_t thread_id;
volatile sig_atomic_t cnt[PTHR];
int i;
int cntr;
pid_t pid, savedpid;
int pstat;
pthread_attr_init(&attrs[0]);
pthread_attr_setdetachstate(&attrs[0], PTHREAD_CREATE_DETACHED);
pthread_attr_setscope(&attrs[0], PTHREAD_SCOPE_PROCESS);
pthread_attr_init(&attrs[1]);
pthread_attr_setdetachstate(&attrs[1], PTHREAD_CREATE_DETACHED);
pthread_attr_setscope(&attrs[1], PTHREAD_SCOPE_SYSTEM);
for(i = 0; i < PTHR; i++) {
cnt[i] = INFL;
if(pthread_create(&thread_id, &attrs[i%NATR],
&test_write, (void *)&cnt[i])){
perror("pthread_create:");
return 1;
}
}
fprintf(stderr, "Threads created.\n");
for (i = 0; i < FRKL; i++) {
fprintf(stderr, "forking\n");
switch(pid = fork()) {
case -1: /* error */
perror("fork fail:");
return 2;
case 0: /* child */
// Child don't use thread related operations
// Only dup() & close()
cntr = CHLD;
test_write(&cntr);
_exit(0);
default: /* parent */
savedpid = pid;
do{
pid = waitpid(savedpid, &pstat, 0);
}while(pid == -1 && errno == EINTR);
break;
}
}
fprintf(stderr, "Threads OK:");
for(i = 0; i < PTHR; i++){
fprintf(stderr, " %d", (int)cnt[i]);
}
fprintf(stderr, "\n");
_exit(0);
return 0;
}
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-threads
mailing list