Hi Everyone,
   I now have an application-level implementation of os.wait() complete.
It's built on top of os.waitpid(), but according to the documentation
I've found, the behavior should be the same.  My test might be a bit
objectionable as well, but I wanted to use a non-zero return value.  I
also modified test_popen() as it wasn't waiting for its children, and
broke my test_os_wait(), since it was waiting for the child processes
created by test_popen().

    In the future it would be desirable to implement os.wait() in terms
of the c wait() function in ll_os.py but currently (at least on Ubuntu
9.10) the c wait() function takes a pointer to a transparent struct,
rather than an int, and that seems to prevent my interpreter level
version from being built.

  I've attached both versions, but the interpreter level version will
not translate.

cheers,
Dan

P.S. This is my first patch, so it's probably worth giving it at least a
once over...
Index: pypy/module/posix/test/test_posix2.py
===================================================================
--- pypy/module/posix/test/test_posix2.py	(revision 69072)
+++ pypy/module/posix/test/test_posix2.py	(working copy)
@@ -394,6 +394,16 @@
             os = self.posix
             raises(ValueError, os.sysconf, "!...@#$%!#$!@#")
 
+    if hasattr(os, 'wait'):
+        def test_os_wait(self):
+            os = self.posix
+            child = os.fork()
+            if child != 0:
+                pid, status = os.wait()
+                assert child == pid
+            else:
+                os._exit(0)
+
     if hasattr(os, 'fsync'):
         def test_fsync(self):
             os = self.posix
Index: pypy/module/posix/__init__.py
===================================================================
--- pypy/module/posix/__init__.py	(revision 69072)
+++ pypy/module/posix/__init__.py	(working copy)
@@ -92,6 +92,8 @@
         interpleveldefs['fork'] = 'interp_posix.fork'
     if hasattr(os, 'waitpid'):
         interpleveldefs['waitpid'] = 'interp_posix.waitpid'
+    if hasattr(os, 'wait'):
+        interpleveldefs['wait'] = 'interp_posix.wait'
     if hasattr(os, 'execv'):
         interpleveldefs['execv'] = 'interp_posix.execv'
     if hasattr(os, 'execve'):
Index: pypy/module/posix/interp_posix.py
===================================================================
--- pypy/module/posix/interp_posix.py	(revision 69072)
+++ pypy/module/posix/interp_posix.py	(working copy)
@@ -514,6 +514,14 @@
     return space.newtuple([space.wrap(pid), space.wrap(status)])
 waitpid.unwrap_spec = [ObjSpace, int, int]
 
+def wait(space):
+    try:
+        pid, status = os.wait()
+    except OSError, e:
+        raise wrap_oserror(space, e)
+    return space.newtuple([space.wrap(pid), space.wrap(status)])
+wait.unwrap_spec = [ObjSpace]
+
 def _exit(space, status):
     os._exit(status)
 _exit.unwrap_spec = [ObjSpace, int]
Index: pypy/rpython/module/ll_os.py
===================================================================
--- pypy/rpython/module/ll_os.py	(revision 69072)
+++ pypy/rpython/module/ll_os.py	(working copy)
@@ -1176,6 +1176,30 @@
                       "ll_os.ll_os_readlink",
                       llimpl=os_readlink_llimpl)
 
+    #TODO: @Ademan
+    @registering_if(os, 'wait')
+    def register_os_wait(self):
+        os_wait = self.llexternal('wait',
+                                  [rffi.INTP],
+                                  rffi.PID_T)
+
+        def os_wait_llimpl():
+            status_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw') # allocate single integer
+            status_p[0] = rffi.cast(rffi.INT, 0)                    # initialize integer
+            result = os_wait(status_p)                              # call function
+            result = rffi.cast(lltype.Signed, result)               # cast
+            status = status_p[0]                                    # retrieve status
+            lltype.free(status_p, flavor='raw')                     # free the integer
+
+            if result == -1:
+                raise OSError(rposix.get_errno(), "os_wait failed")
+            return (rffi.cast(lltype.Signed, result),
+                    rffi.cast(lltype.Signed, status))
+
+        return extdef([], (int, int),
+                      "ll_os.ll_os_wait",
+                      llimpl=os_wait_llimpl)
+
     @registering(os.waitpid)
     def register_os_waitpid(self):
         if sys.platform.startswith('win'):
Index: pypy/module/posix/test/test_posix2.py
===================================================================
--- pypy/module/posix/test/test_posix2.py	(revision 69498)
+++ pypy/module/posix/test/test_posix2.py	(working copy)
@@ -291,6 +291,10 @@
             stream = os.popen('echo 1')
             assert stream.read() == '1\n'
 
+        try:
+            while True: os.wait()
+        except OSError: pass
+
     if hasattr(__import__(os.name), '_getfullpathname'):
         def test__getfullpathname(self):
             # nt specific
@@ -393,7 +397,23 @@
         def test_os_sysconf_error(self):
             os = self.posix
             raises(ValueError, os.sysconf, "!...@#$%!#$!@#")
+    
+    if hasattr(os, 'wait'):
+        def test_os_wait(self):
+            os = self.posix
+            exit_status = 0x33
 
+            if not hasattr(os, "fork"):
+                skip("Need fork() to test wait()")
+            child = os.fork()
+            if child == 0: # in child
+                os._exit(exit_status)
+            else:
+                pid, status = os.wait()
+                assert child == pid
+                assert status >> 8 == exit_status # check exit status
+                assert status & 0x00FF == 0       # signal 0
+
     if hasattr(os, 'fsync'):
         def test_fsync(self):
             os = self.posix
Index: pypy/module/posix/__init__.py
===================================================================
--- pypy/module/posix/__init__.py	(revision 69498)
+++ pypy/module/posix/__init__.py	(working copy)
@@ -26,6 +26,9 @@
                 'popen3' : 'app_posix.popen3',
                 'popen4' : 'app_posix.popen4',
                 })
+
+    if hasattr(os, 'wait'):
+        appleveldefs['wait'] = 'app_posix.wait'
         
     interpleveldefs = {
     'open'      : 'interp_posix.open',
Index: pypy/module/posix/app_posix.py
===================================================================
--- pypy/module/posix/app_posix.py	(revision 69498)
+++ pypy/module/posix/app_posix.py	(working copy)
@@ -153,6 +153,10 @@
             try_close(read_end)
             raise Exception, e     # bare 'raise' does not work here :-(
 
+    def wait():
+        import os
+        return os.waitpid(-1, 0)
+
 else:
     # Windows implementations
     
_______________________________________________
[email protected]
http://codespeak.net/mailman/listinfo/pypy-dev

Reply via email to