Skip to content

Commit

Permalink
Make nested errfile test more robust
Browse files Browse the repository at this point in the history
  • Loading branch information
danijar committed Sep 12, 2024
1 parent 74730c2 commit c04d078
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 19 deletions.
1 change: 1 addition & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 3
strategy:
fail-fast: False
matrix:
Expand Down
1 change: 0 additions & 1 deletion portal/client_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ def connected(self):
return self.isconn.is_set()

def connect(self, timeout=None):
assert not self.connected
if not self.options.autoconn:
self.wantconn.set()
return self.isconn.wait(timeout)
Expand Down
70 changes: 52 additions & 18 deletions tests/test_errfile.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import pathlib
import time

Expand Down Expand Up @@ -58,31 +59,64 @@ def fn2(barrier, errfile):
@pytest.mark.parametrize('repeat', range(3))
def test_nested_procs(self, tmpdir, repeat):
errfile = pathlib.Path(tmpdir) / 'error'
ready = portal.context.mp.Semaphore(0)
ready = portal.context.mp.Barrier(7)
queue = portal.context.mp.Queue()

def hang():
def outer(ready, queue, errfile):
portal.setup(errfile=errfile, interval=0.1)
portal.Process(inner, ready, queue, name='inner', start=True)
portal.Thread(hang_thread, ready, start=True)
portal.Process(hang_process, ready, queue, start=True)
queue.put(os.getpid())
queue.close()
queue.join_thread()
ready.wait() # 1
while True:
time.sleep(0.1)

def outer(ready, errfile):
portal.setup(errfile=errfile, interval=0.1)
portal.Process(inner, ready, errfile, name='inner', start=True)
portal.Thread(hang, start=True)
portal.Process(hang, start=True)
ready.release()
hang()

def inner(ready, errfile):
portal.setup(errfile=errfile, interval=0.1)
portal.Thread(hang, start=True)
portal.Process(hang, start=True)
ready.release()
def inner(ready, queue):
assert portal.context.errfile
portal.Thread(hang_thread, ready, start=True)
portal.Process(hang_process, ready, queue, start=True)
queue.put(os.getpid())
queue.close()
queue.join_thread()
ready.wait() # 2
raise ValueError('reason')

Check failure on line 85 in tests/test_errfile.py

View workflow job for this annotation

GitHub Actions / build (3.9)

reason

Check failure on line 85 in tests/test_errfile.py

View workflow job for this annotation

GitHub Actions / build (3.9)

reason

Check failure on line 85 in tests/test_errfile.py

View workflow job for this annotation

GitHub Actions / build (3.9)

reason

Check failure on line 85 in tests/test_errfile.py

View workflow job for this annotation

GitHub Actions / build (3.10)

reason

Check failure on line 85 in tests/test_errfile.py

View workflow job for this annotation

GitHub Actions / build (3.10)

reason

Check failure on line 85 in tests/test_errfile.py

View workflow job for this annotation

GitHub Actions / build (3.10)

reason

Check failure on line 85 in tests/test_errfile.py

View workflow job for this annotation

GitHub Actions / build (3.11)

reason

Check failure on line 85 in tests/test_errfile.py

View workflow job for this annotation

GitHub Actions / build (3.11)

reason

Check failure on line 85 in tests/test_errfile.py

View workflow job for this annotation

GitHub Actions / build (3.11)

reason

worker = portal.Process(outer, ready, errfile, name='outer', start=True)
ready.acquire()
ready.acquire()
def hang_thread(ready):
ready.wait() # 3, 4
while True:
time.sleep(0.1)

def hang_process(ready, queue):
assert portal.context.errfile
queue.put(os.getpid())
queue.close()
queue.join_thread()
ready.wait() # 5, 6
while True:
time.sleep(0.1)

worker = portal.Process(
outer, ready, queue, errfile, name='outer', start=True)
ready.wait() # 7
worker.join()
content = errfile.read_text()
assert "Error in 'inner' (ValueError: reason):" == content.split('\n')[0]
assert not worker.running
pids = [queue.get() for _ in range(4)]
time.sleep(2.0) # On some systems this can take a while.
assert not alive(pids[0])
assert not alive(pids[1])
assert not alive(pids[2])
assert not alive(pids[3])


def alive(pid):
try:
os.kill(pid, 0)
except OSError:
assert True
else:
assert False

0 comments on commit c04d078

Please sign in to comment.