Date: Mon, 5 Mar 2007 19:21:03 GMT From: "Jukka A. Ukkonen"<jau@iki.fi> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/109946: Compatibility: FreeBSD has been missing WNOWAIT flag for wait*() calls Message-ID: <200703051921.l25JL3ae015639@www.freebsd.org> Resent-Message-ID: <200703051930.l25JU2Je074356@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 109946 >Category: kern >Synopsis: Compatibility: FreeBSD has been missing WNOWAIT flag for wait*() calls >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Mon Mar 05 19:30:01 GMT 2007 >Closed-Date: >Last-Modified: >Originator: Jukka A. Ukkonen >Release: 6.2-STABLE >Organization: private person >Environment: FreeBSD mjolnir 6.2-STABLE FreeBSD 6.2-STABLE #1: Fri Mar 2 08:08:33 EET 2007 root@mjolnir:/usr/obj/usr/src/sys/Mjolnir i386 >Description: Were there a problem class compatibility errors, I would have classified this as belonging to such a category. SUS required WNOWAIT flag for wait*() calls already long ago. Anyhow FreeBSD has not introduced one, though, implementing it is relatively easy. Simply do everything as with a normal wait*() call cutting the syscall short just before actually releasing the proc struct belonging to the zombie. The availability of the WNOWAIT flag allows one to wait for any child from within a thread which has no idea of child processes created by other threads. With WNOWAIT set one can first poll for a child to see whether the pid is one that is known to the calling thread. If the child is known, the code can then call waitpid() or wait4() with the pid of the found process and without WNOWAIT to reap its process struct. If the child is unknown, the code can simply give up waiting and let another thread, take its turn waiting for the child. This allows the thread that created the child process to eventually find the child and collect its exit status. This is especially useful when implementing a threaded library which might fork child processes which are otherwise completely unknown in the program, but the library still needs to know when the child process has terminated. A library OTOH cannot expect to know anything about the programs in which it is going to be used. >How-To-Repeat: See /usr/include/sys/wait.h - there is no WNOWAIT. >Fix: Apply the attached patch. And, please, MFC it before 7.x goes out. Relatively straight forward things like this really do not deserve to linger in the HEAD until the next major release. Patch attached with submission follows: --- src/sys/sys/wait.h.orig Mon Mar 5 20:11:30 2007 +++ src/sys/sys/wait.h Mon Mar 5 20:40:32 2007 @@ -78,7 +78,9 @@ */ #define WNOHANG 1 /* Don't hang in wait. */ #define WUNTRACED 2 /* Tell about stopped, untraced children. */ +#define WSTOPPED WUNTRACED /* SUS compatibility */ #define WCONTINUED 4 /* Report a job control continued process. */ +#define WNOWAIT 8 /* Poll only. Don't delete the proc entry. */ #if __BSD_VISIBLE #define WLINUXCLONE 0x80000000 /* Wait for kthread spawned from linux_clone. */ --- src/sys/kern/kern_exit.c.orig Mon Mar 5 20:17:19 2007 +++ src/sys/kern/kern_exit.c Mon Mar 5 20:34:10 2007 @@ -590,7 +590,7 @@ pid = -q->p_pgid; PROC_UNLOCK(q); } - if (options &~ (WUNTRACED|WNOHANG|WCONTINUED|WLINUXCLONE)) + if (options &~ (WUNTRACED|WNOHANG|WCONTINUED|WNOWAIT|WLINUXCLONE)) return (EINVAL); loop: if (q->p_flag & P_STATCHILD) { @@ -663,6 +663,26 @@ psignal(t, SIGCHLD); wakeup(t); PROC_UNLOCK(t); + sx_xunlock(&proctree_lock); + return (0); + } + + if (! (options & WNOWAIT)) { + /* + * SUS compatibility. + * + * We poll only returning the status. + * We do not wish to release the proc + * struct just yet. + * ==> If another thread created this + * process, it is sometimes better to + * leave this one as is for now and let + * the other thread reap the remnants + * of the child instead of automatically + * destroying the proc entry and making + * it impossible for the other thread to + * wait for its own child process. + */ sx_xunlock(&proctree_lock); return (0); } >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200703051921.l25JL3ae015639>