3

The os.waitpid docs https://docs.python.org/2.7/library/os.html#os.WNOHANG say that if the child process is not yet exited, then the return value will be (0,0) however on FreeBSD (FreeBSD 10.3-RELEASE-p7) sometimes (0,-512) or (0,-2048) is returned. Example program:

#!/usr/bin/env python

import os
import sys
import time

def show_waitpid_results(results):
    print("results: %s" % (str(results)))
    print("core: %r continued: %r stopped: %r signaled: %r exited %r" %
        (
            os.WCOREDUMP(results[1]),
            os.WIFCONTINUED(results[1]),
            os.WIFSTOPPED(results[1]),
            os.WIFSIGNALED(results[1]),
            os.WIFEXITED(results[1]))
        )
    if os.WIFEXITED(results[1]):
        print("exit code: %r" % (os.WEXITSTATUS(results[1])))

if __name__ == '__main__':
    try:
        pid = os.fork()
        if pid:
            print("in parent. child pid: %r" % (pid))
            while True:
                waitpid_result = os.waitpid(pid, os.WNOHANG)
                show_waitpid_results(waitpid_result)
                if waitpid_result == (0,0) or waitpid_result == (0,-512):
                    time.sleep(.1)
                    pass
                else:
                    break
            print("parent exiting")
        else:
            # child
            time.sleep(.5)
            print("child exiting with exit code 10");
            sys.exit(10)
    except Exception:
        e = sys.exc_info()[1]
        print("error: %s"%(e))
        sys.exit(20)

Correct output (similar/same) on osx (Python 2.7.11) and ubuntu (Python 2.7.6)

in parent. child pid: 3196
results: (0, 0)
core: False continued: False stopped: False signaled: False exited True
exit code: 0
results: (0, 0)
core: False continued: False stopped: False signaled: False exited True
exit code: 0
results: (0, 0)
core: False continued: False stopped: False signaled: False exited True
exit code: 0
results: (0, 0)
core: False continued: False stopped: False signaled: False exited True
exit code: 0
results: (0, 0)
core: False continued: False stopped: False signaled: False exited True
exit code: 0
child exiting with exit code 10
results: (0, 0)
core: False continued: False stopped: False signaled: False exited True
exit code: 0
results: (3196, 2560)
core: False continued: False stopped: False signaled: False exited True
exit code: 10
parent exiting

Incorrect? behavior on FreeBSD (Python 2.7.12):

in parent. child pid: 5054
results: (0, -512)
core: False continued: False stopped: False signaled: False exited True
exit code: -2
results: (0, -512)
core: False continued: False stopped: False signaled: False exited True
exit code: -2
results: (0, -512)
core: False continued: False stopped: False signaled: False exited True
exit code: -2
results: (0, -512)
core: False continued: False stopped: False signaled: False exited True
exit code: -2
results: (0, -512)
core: False continued: False stopped: False signaled: False exited True
exit code: -2
child exiting with exit code 10
results: (5054, 2560)
core: False continued: False stopped: False signaled: False exited True
exit code: 10
parent exiting

I have also seen -2048 vs. -512 under FreeBSD.

Maybe the status value (second element in returned tuple) is not initialized properly on FreeBSD when os.WNOHANG is used? Can I not rely on waitpid returning (0,0)?

clucas
  • 166
  • 2
  • 9
  • From briefly looking at [kern_exit.c](https://svnweb.freebsd.org/base/releng/10.3/sys/kern/kern_exit.c?view=markup): yes. If WNOHANG is given as an option to waitpid and there's nothing to report, 0 is returned, and the variable kern_exit.c::sys_wait4::status remains uninitialized garbage but is still copied out to the user's `status` argument. – Mark Plotnick Aug 18 '16 at 21:40
  • Thanks @MarkPlotnick for the pointer. I verified with a [C program](https://gist.github.com/caseylucas/df2eea85741ea892328c3f8c558cfa75) that I get the same (trashed) -512 behavior. Now I wonder if is this a FreeBSD bug or a bug (invalid assumption? or documentation error?) on the Python side. – clucas Aug 19 '16 at 23:35
  • I think it's a FreeBSD bug. I read the [waitpid](http://pubs.opengroup.org/onlinepubs/9699919799/functions/waitpid.html) page of the POSIX standard, and although the system isn't required to return anything meaningful in *status if there's nothing for waitpid to report, returning the contents of an uninitialized kernel variable is a potential information leak. – Mark Plotnick Aug 20 '16 at 03:11

0 Answers0