threads/76694: fork cause hang in dup()/close() function inchild (-lc_r)

Julian Elischer julian at elischer.org
Wed Jan 26 16:40:25 PST 2005


The following reply was made to PR threads/76694; it has been noted by GNATS.

From: Julian Elischer <julian at elischer.org>
To: Serguei Leontiev <lse at CryptoPro.ru>
Cc: freebsd-gnats-submit at freebsd.org
Subject: Re: threads/76694: fork cause hang in dup()/close() function in child
 (-lc_r)
Date: Wed, 26 Jan 2005 16:30:29 -0800

 this may seem harsh, but 5.2.1 was still an experimental branch..
 you should upgrade to 5.3 where lkse is the defualt (called libpthread).
 libc_r will not be "actively" maintained after we settle on a kernel 
 supported threading package.
 
 
 Serguei Leontiev wrote:
 
 >>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:
 >>    
 >>
 >_______________________________________________
 >freebsd-threads at freebsd.org mailing list
 >http://lists.freebsd.org/mailman/listinfo/freebsd-threads
 >To unsubscribe, send any mail to "freebsd-threads-unsubscribe at freebsd.org"
 >  
 >
 


More information about the freebsd-threads mailing list