Skip to content

Commit

Permalink
Now uses posix_spawn to avoid deadlock
Browse files Browse the repository at this point in the history
  • Loading branch information
dshachter committed Oct 21, 2019
1 parent d7eae2c commit 0f386ed
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
WARNING: This library is unsafe to use until python 3.8 is released due to deadlock issues with fork().
WARNING: This library requires python 3.8

# Fastprocess
A fast subprocess library
Expand Down
10 changes: 7 additions & 3 deletions benchmark/bench
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ export PYTHONPATH=$(realpath ${scriptdir}/..)
printf %"$(tput cols)"s |tr " " "-"
echo
echo "10000 spawns with fork and exec..."
time ${scriptdir}/forktest.py
time python ${scriptdir}/forktest.py
printf %"$(tput cols)"s |tr " " "-"
echo
echo "10000 spawns with fastprocess..."
time ${scriptdir}/fptest.py
time python ${scriptdir}/fptest.py
printf %"$(tput cols)"s |tr " " "-"
echo
echo "10000 spawns with old fastprocess..."
time python ${scriptdir}/old_fptest.py
printf %"$(tput cols)"s |tr " " "-"
echo
echo "10000 spawns with subprocess..."
time ${scriptdir}/sptest.py
time python ${scriptdir}/sptest.py
printf %"$(tput cols)"s |tr " " "-"
8 changes: 8 additions & 0 deletions benchmark/old_fptest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/python3

from fastprocess import FastProcess, OldFastProcess

procs = []

for i in range(10000):
procs.append(OldFastProcess(['echo', 'hello', 'world'], stdout=open('/dev/null', 'w')))
2 changes: 1 addition & 1 deletion fastprocess/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from fastprocess.fastprocess import FastProcess
from fastprocess.fastprocess import FastProcess, OldFastProcess
24 changes: 24 additions & 0 deletions fastprocess/fastprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,30 @@
import signal

class FastProcess:
def __init__(self, cmd, stdin=None, stdout=None, stderr=None, env=None):
file_actions = []
if stdin:
file_actions.append((os.POSIX_SPAWN_DUP2, stdin.fileno(), 0))
if stdout:
file_actions.append((os.POSIX_SPAWN_DUP2, stdout.fileno(), 1))
if stderr:
file_actions.append((os.POSIX_SPAWN_DUP2, stderr.fileno(), 2))
self.pid = os.posix_spawnp(cmd[0], cmd, env if env else os.environ, file_actions=file_actions)

def __del__(self):
os.kill(self.pid, signal.SIGTERM)

def terminate(self):
os.kill(self.pid, signal.SIGTERM)

def signal(self, sig):
os.kill(self.pid, sig)

def wait(self):
return os.WEXITSTATUS(os.waitpid(self.pid, 0)[1])


class OldFastProcess:
def __init__(self, cmd, stdin=None, stdout=None, stderr=None):
self.pid = os.fork()
if self.pid == 0:
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@

setup(
name='fastprocess',
version='0.1.0',
version='1.0.0',
author='Dylan Stephano-Shachter',
author_email='[email protected]',
description=('A fast subprocess library'),
license='LGPL',
url='https://github.com/dstathis/fastprocess',
packages=['fastprocess'],
python_requires='>=3.8',
long_description=open(
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'README.md')
).read(),
Expand Down

0 comments on commit 0f386ed

Please sign in to comment.