bin/145884: script: Racy return value

Lucius Windschuh lwindschuh at
Tue Apr 20 14:10:05 UTC 2010

>Number:         145884
>Category:       bin
>Synopsis:       script: Racy return value
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Apr 20 14:10:03 UTC 2010
>Originator:     Lucius Windschuh
>Release:        9-CURRENT (i386)
FreeBSD t400 9.0-CURRENT FreeBSD 9.0-CURRENT #139 r206412MP: Fri Apr  9 11:14:32 CEST 2010     root at t400:/usr/obj/usr/src/sys/CURRENT  i386
script -qa $some_file $some_cmd is supposed to return the same value that the execution of $some_cmd gave (TODO: This is not mentioned in the man page).
Unfortunately, script's return value changes randomly between zero and the expected value.

I am a bit uncertain if this is a kernel or userland bug.

As you see in the proposed patch, waiting for the child process to die instead of simply looking for a dead child solves the issue. So either the child is not dead when script tries to exit or the kernel has not yet marked the child dead?

Another bit: "ktrace script -qa /tmp/foobar false" always returns the right result: ktrace stops the race, as it seems.

Besides this, I was seeing this problem for quite a while (some months, I think). This indicates that it was not introduced by a recent commit.

This bug made portupgrade hardly usable, as it did not reliably realize that the build process has failed.
Execute this command many times:
$ script -qa /tmp/foobar false && echo "This should not happen"

And sometimes, you see "This should not happen" which, well, should not happen. :-)
See the attached file: Remove WNOHANG. I think that it does the right thing as wait3 returns immediately if no child process exists, so that finish() will return after the last child exited, which is exactly the point at which script shall return.

Patch attached with submission follows:

Index: src/usr.bin/script/script.c
--- src/usr.bin/script/script.c	(revision 206560)
+++ src/usr.bin/script/script.c	(working copy)
@@ -223,7 +223,7 @@
 	int die, e, status;
 	die = e = 0;
-	while ((pid = wait3(&status, WNOHANG, 0)) > 0)
+	while ((pid = wait3(&status, 0, 0)) > 0)
 	        if (pid == child) {
 			die = 1;
 			if (WIFEXITED(status))


More information about the freebsd-bugs mailing list