From owner-freebsd-threads@FreeBSD.ORG Wed Dec 2 17:14:06 2009 Return-Path: Delivered-To: freebsd-threads@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2C68D1065670 for ; Wed, 2 Dec 2009 17:14:06 +0000 (UTC) (envelope-from gprspb@mail.ru) Received: from mailgw.nnz-home.ru (mailgw.nnz-home.ru [87.249.56.38]) by mx1.freebsd.org (Postfix) with ESMTP id 9EF578FC0A for ; Wed, 2 Dec 2009 17:14:05 +0000 (UTC) Received: from localhost (unknown [127.0.0.1]) by mailgw.nnz-home.ru (Postfix) with ESMTP id 78185284AC for ; Wed, 2 Dec 2009 19:57:47 +0300 (MSK) X-Virus-Scanned: amavisd-new at mailgw.nnz-home.ru Received: from mailgw.nnz-home.ru ([127.0.0.1]) by localhost (mailgw.nnz-home.ru [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id X8Lc+oK6y3lR for ; Wed, 2 Dec 2009 19:57:47 +0300 (MSK) Received: from gpr.nnz-home.ru (unknown [10.44.111.151]) by mailgw.nnz-home.ru (Postfix) with ESMTP id 3544D28456 for ; Wed, 2 Dec 2009 19:57:47 +0300 (MSK) Received: from gpr by gpr.nnz-home.ru with local (Exim 4.69) (envelope-from ) id 1NFsVT-0000Vb-Jb for freebsd-threads@freebsd.org; Wed, 02 Dec 2009 19:56:47 +0300 Date: Wed, 2 Dec 2009 19:56:47 +0300 From: Gennady Proskurin To: freebsd-threads@freebsd.org Message-ID: <20091202165647.GA1944@gpr.nnz-home.ru> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="h31gzZEtNLTqOjlF" Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) Subject: pipe with threads X-BeenThere: freebsd-threads@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Threading on FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Dec 2009 17:14:06 -0000 --h31gzZEtNLTqOjlF Content-Type: text/plain; charset=us-ascii Content-Disposition: inline I use usual scenario for writing data to stdin of some other program: 1. pipe, fork 2. Child: dup2, exec. Parent: write When my program is single-threaded (or may be multithreaded, with only one thread running this scenario), all works fine. But when this scenario executed concurently by many threads, the reading process sometimes doesn't see, that pipe was closed and reading process is stuck in read() (piperd wchan), and write process is stuck in waitpid. Is it a bug somewhere or I missing something? Test program attached. I compile it with "cc -o pipetest pipetest.c -pthread" And run: "while [ 1 ]; do ./pipetest ; done" My system: fresh 9-currend/amd64, smp (2 CPU) --h31gzZEtNLTqOjlF Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="pipetest.c" #include #include #include #include #include static char data[10]; void* thr_func(void* arg) { int pipe_fd[2]; int pid; const char* buf = data; int write_remain = sizeof(data); int waitpid_status; int waitpid_res; int bar_res; if (pipe(pipe_fd)<0) { perror("pipe()"); _exit(1); } printf("fd: %i %i\n", pipe_fd[0], pipe_fd[1]); pid = fork(); switch(pid) { case -1: perror("fork()"); _exit(1); case 0: if (close(pipe_fd[1])) { perror("close()"); _exit(1); } if (dup2(pipe_fd[0], STDIN_FILENO) == -1) { perror("dup2()"); _exit(1); } execl("/bin/sh", "sh", "-c", "cat > /dev/null", 0); perror("exec()"); _exit(1); } if (close(pipe_fd[0])) { perror("close()"); _exit(1); } // write data while (write_remain>0) { int w = write(pipe_fd[1], buf, write_remain); if (w>0) { buf += w; write_remain -= w; printf("write:%i\n", w); } else { perror("write()"); _exit(1); } } if (close(pipe_fd[1])) { perror("close()"); _exit(1); } // wait child waitpid_res = waitpid(pid, &waitpid_status, 0); if (waitpid_res != pid) { perror("waitpid()"); _exit(1); } return 0; } int main() { pthread_t thr1, thr2; sigset_t mask; // block SIGCHLD sigemptyset(&mask); sigaddset(&mask, SIGCHLD); if (sigprocmask(SIG_BLOCK, &mask, 0)) { perror("sigprocmask()"); _exit(1); } // create threads if (pthread_create(&thr1,0,thr_func,0) || pthread_create(&thr2,0,thr_func,0)) { perror("pthread_create()"); _exit(1); } // join threads if (pthread_join(thr1,0) || pthread_join(thr2,0)) { perror("pthread_join()"); _exit(1); } printf("OK\n"); return 0; } --h31gzZEtNLTqOjlF--