From 420f6575c97759611d56d06034c17fe9d347cf20 Mon Sep 17 00:00:00 2001 From: ET Date: Mon, 20 Mar 2017 11:26:54 -0500 Subject: [PATCH 1/4] check process status for non-child process --- ptyprocess/ptyprocess.py | 46 +++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/ptyprocess/ptyprocess.py b/ptyprocess/ptyprocess.py index cb3efae..da0b22e 100644 --- a/ptyprocess/ptyprocess.py +++ b/ptyprocess/ptyprocess.py @@ -699,10 +699,25 @@ def isalive(self): except OSError as e: # No child processes if e.errno == errno.ECHILD: - raise PtyProcessError('isalive() encountered condition ' + - 'where "terminated" is 0, but there was no child ' + - 'process. Did someone else call waitpid() ' + - 'on our process?') + try: + os.kill(self.pid, 0) + except OSError as err: + if err.errno == errno.ESRCH: + # No such process + raise PtyProcessError('isalive() encountered condition ' + + 'where "terminated" is 0, but there was no child ' + + 'process. Did someone else call waitpid() ' + + 'on our process?') + elif err.errno == errno.EPERM: + # Process deny access + raise PtyProcessError('isalive() encountered condition ' + + 'where the child process deny access') + else: + # Other possible error + raise err + else: + # Process exists not as child + pid, status = 0, 0 else: raise @@ -717,10 +732,25 @@ def isalive(self): except OSError as e: # pragma: no cover # This should never happen... if e.errno == errno.ECHILD: - raise PtyProcessError('isalive() encountered condition ' + - 'that should never happen. There was no child ' + - 'process. Did someone else call waitpid() ' + - 'on our process?') + try: + os.kill(self.pid, 0) + except OSError as err: + if err.errno == errno.ESRCH: + # No such process + raise PtyProcessError('isalive() encountered condition ' + + 'where "terminated" is 0, but there was no child ' + + 'process. Did someone else call waitpid() ' + + 'on our process?') + elif err.errno == errno.EPERM: + # Process deny access + raise PtyProcessError('isalive() encountered condition ' + + 'where the child process deny access') + else: + # Other possible error + raise err + else: + # Process exists not as child + pid, status = 0, 0 else: raise From 538430bdfe5f5f7a4a4f567a26718b8b2911b447 Mon Sep 17 00:00:00 2001 From: masteret Date: Wed, 17 May 2017 16:39:31 -0500 Subject: [PATCH 2/4] adopting code from psutil to determine system type --- ptyprocess/ptyprocess.py | 53 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/ptyprocess/ptyprocess.py b/ptyprocess/ptyprocess.py index da0b22e..ee8db1e 100644 --- a/ptyprocess/ptyprocess.py +++ b/ptyprocess/ptyprocess.py @@ -700,7 +700,49 @@ def isalive(self): # No child processes if e.errno == errno.ECHILD: try: - os.kill(self.pid, 0) + """ + The following code is adopted from psutil with slight modification + + https://github.com/giampaolo/psutil/blob/master/LICENSE + psutil is distributed under BSD license reproduced below. + + Copyright (c) 2009, Jay Loden, Dave Daeschler, Giampaolo Rodola' + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the psutil authors nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + """ + if sys.platform.startswith("linux"): + os.kill(self.pid, 0) + elif sys.platform.startswith("darwin"): + pass + elif sys.platform.startswith("freebsd"): + pass + else: + pass + """ + The adoption of psutil code ends here + """ except OSError as err: if err.errno == errno.ESRCH: # No such process @@ -733,7 +775,14 @@ def isalive(self): # This should never happen... if e.errno == errno.ECHILD: try: - os.kill(self.pid, 0) + if sys.platform.startswith("linux"): + os.kill(self.pid, 0) + elif sys.platform.startswith("darwin"): + pass + elif sys.platform.startswith("freebsd"): + pass + else: + pass except OSError as err: if err.errno == errno.ESRCH: # No such process From c8b0f7f03b150bb364d92773d952e9faec88e4d5 Mon Sep 17 00:00:00 2001 From: masteret Date: Wed, 17 May 2017 16:59:47 -0500 Subject: [PATCH 3/4] add license text to 2nd part of code also --- ptyprocess/ptyprocess.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/ptyprocess/ptyprocess.py b/ptyprocess/ptyprocess.py index ee8db1e..bbaf961 100644 --- a/ptyprocess/ptyprocess.py +++ b/ptyprocess/ptyprocess.py @@ -775,6 +775,38 @@ def isalive(self): # This should never happen... if e.errno == errno.ECHILD: try: + """ + The following code is adopted from psutil with slight modification + + https://github.com/giampaolo/psutil/blob/master/LICENSE + psutil is distributed under BSD license reproduced below. + + Copyright (c) 2009, Jay Loden, Dave Daeschler, Giampaolo Rodola' + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the psutil authors nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + """ if sys.platform.startswith("linux"): os.kill(self.pid, 0) elif sys.platform.startswith("darwin"): From dd90b0860ac2ba46d44d9b4d9a2186788286c509 Mon Sep 17 00:00:00 2001 From: masteret Date: Thu, 18 May 2017 10:51:08 -0500 Subject: [PATCH 4/4] add zombie process check for linux --- ptyprocess/ptyprocess.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/ptyprocess/ptyprocess.py b/ptyprocess/ptyprocess.py index bbaf961..d2e02d6 100644 --- a/ptyprocess/ptyprocess.py +++ b/ptyprocess/ptyprocess.py @@ -732,8 +732,17 @@ def isalive(self): (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ + os.kill(self.pid, 0) if sys.platform.startswith("linux"): - os.kill(self.pid, 0) + with open("/proc/%s/stat" % (self.pid), "rb") as f: + data = f.read() + rpar = data.rfind(b')') + name = data[data.find(b'(') + 1:rpar] + fields_after_name = data[rpar + 2:].split() + if fields_after_name[0] == "Z": + raise PtyProcessError('isalive() encountered condition ' + + 'where the child process becomes a zombie process.' + + ' Does other process kill the ptyprocess?') elif sys.platform.startswith("darwin"): pass elif sys.platform.startswith("freebsd"): @@ -807,8 +816,17 @@ def isalive(self): (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ + os.kill(self.pid, 0) if sys.platform.startswith("linux"): - os.kill(self.pid, 0) + with open("/proc/%s/stat" % (self.pid), "rb") as f: + data = f.read() + rpar = data.rfind(b')') + name = data[data.find(b'(') + 1:rpar] + fields_after_name = data[rpar + 2:].split() + if fields_after_name[0] == "Z": + raise PtyProcessError('isalive() encountered condition ' + + 'where the child process becomes a zombie process.' + + ' Does other process kill the ptyprocess?') elif sys.platform.startswith("darwin"): pass elif sys.platform.startswith("freebsd"):