Date: Sat, 21 Oct 2000 09:09:56 -0700 (PDT) From: grubba@roxen.com To: freebsd-gnats-submit@FreeBSD.org Subject: misc/22190: A threaded read(2) from a socketpair(2) fd can sometimes fail with errno 19 (ENODEV) Message-ID: <20001021160956.9375F37B4C5@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 22190 >Category: misc >Synopsis: A threaded read(2) from a socketpair(2) fd can sometimes fail with errno 19 (ENODEV) >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sat Oct 21 09:10:01 PDT 2000 >Closed-Date: >Last-Modified: >Originator: Henrik Grubbström >Release: 4.0-RELEASE #0 >Organization: Roxen Internet Software >Environment: FreeBSD snok.idonex.se 4.0-RELEASE FreeBSD 4.0-RELEASE #0: Wed Mar 15 02:16:55 GMT 2000 jkh@monster.cdrom.com:/usr/src/sys/compile/GENERIC i386 >Description: In the testsuite for a threaded application, a process spawning test that spawns 1000 /bin/cat /dev/null and waits for them sometimes fails because read(2) returns -1 with errno set to 19 (ENODEV). ENODEV is not a documented error code for read(2). Down-stripped code that triggs the bug: { pid_t pid=-2; int control_pipe[2]; /* Used for communication with the child. */ char buf[4]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, control_pipe) < 0) { error("Failed to create child communication pipe.\n"); } { int loop_cnt = 0; sigset_t new_sig, old_sig; sigfillset(&new_sig); while(sigprocmask(SIG_BLOCK, &new_sig, &old_sig)) ; do { pid=fork(); if (pid == -1) { if (errno == EAGAIN) { /* Process table full or similar. * Try sleeping for a bit. */ if (loop_cnt++ < 60) { /* Don't sleep for too long... */ poll(NULL, 0, 100); /* Try again */ continue; } } else if (errno == EINTR) { /* Try again */ continue; } } break; } while(1); while(sigprocmask(SIG_SETMASK, &old_sig, 0)) ; } if(pid == -1) { int e = errno; /* * fork() failed */ while(close(control_pipe[0]) < 0 && errno==EINTR); while(close(control_pipe[1]) < 0 && errno==EINTR); error("Process.create_process(): fork() failed. errno:%d\n", e); } else if(pid) { int olderrno; /* * The parent process */ /* Close our child's end of the pipe. */ while(close(control_pipe[1]) < 0 && errno==EINTR); /* Wake up the child. */ buf[0] = 0; while (((e = write(control_pipe[0], buf, 1)) < 0) && (errno == EINTR)) ; if(e!=1) { /* Paranoia in case close() sets errno. */ olderrno = errno; while(close(control_pipe[0]) < 0 && errno==EINTR) ; error("Child process died prematurely. (e=%d errno=%d)\n", e, olderrno); } /* Wait for exec or error */ while (((e = read(control_pipe[0], buf, 3)) < 0) && (errno == EINTR)) ; /* Paranoia in case close() sets errno. */ olderrno = errno; while(close(control_pipe[0]) < 0 && errno==EINTR) ; if (!e) { /* OK! */ pop_n_elems(args); push_int(0); return; } else { /* Something went wrong. */ switch(buf[0]) { /* ... */ case 0: /* read() probably failed. */ default: /****************************************************************** * This point is reached with buf = {0, 4, 0}, e = -1, olderrno=19. *****************************************************************/ error("Process.create_process(): " "Child failed: %d, %d, %d, %d, %d!\n", buf[0], buf[1], buf[2], e, olderrno); break; } } }else{ /* * The child process */ /* Close our parent's end of the pipe. */ while(close(control_pipe[0]) < 0 && errno==EINTR); /* Ensure that the pipe will be closed when the child starts. */ if(set_close_on_exec(control_pipe[1], 1) < 0) PROCERROR(PROCE_CLOEXEC, 0); /* Wait for parent to get ready... */ while ((( e = read(control_pipe[1], buf, 1)) < 0) && (errno == EINTR)) ; /* ... */ execvp(argv[0], argv); PROCERROR(PROCE_EXEC, 0); exit(99); } } For the full source, please check src/signal_handler.c:f_create_process() in a Pike distribution. Testsuite report: testsuite: Test 9406 (shift 0) (CRNL) failed. 1: mixed a() { for(int x=0;x<10;x++) { for(int e=0;e<100;e++) if(Process.create_process(({"/bin/cat","/dev/null"}))->wait()) return e; __signal_watchdog(); } return -1;; } 2: mixed b() { return -1; } Error: Process.create_process(): Child failed: 0, 4, 0, -1, 19! __builtin.create_process: create(({"/bin/cat","/dev/null"})) __builtin: create_process() testsuite: Test 9406 (shift 0) (CRNL):1: a() /tmp/autobuild/pike7.1-20001021082826.tar/bin/test_pike.pike:572: main(3,({"/tmp/autobuild/pike7.1-20001021082826.tar/bin/test_pike.pike","modules/CommonLog/module_testsuite","modules/Gdbm/module_testsuite","modules/Gettext/module_testsuite","modules/Gmp/module_testsuite",,,34})) >How-To-Repeat: Unfortunately, the problem is intermittent. It may be triggered by resource exhaustion. >Fix: >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001021160956.9375F37B4C5>