Skip to content

Commit 995980b

Browse files
committed
Test: add non-regression test for handling of exceptions.
Also, make memory_profiler return in case of exception instead of shutting down the full program.
1 parent 091d314 commit 995980b

4 files changed

Lines changed: 24 additions & 10 deletions

File tree

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ test:
1414
$(PYTHON) test/test_import.py
1515
$(PYTHON) test/test_memory_usage.py
1616
$(PYTHON) test/test_precision_import.py
17+
$(PYTHON) test/test_exception.py

README.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,8 @@ cleanup.
447447

448448
`Benjamin Bengfort <https://github.com/bbengfort>`_ added support for tracking the usage of individual child processes and plotting them.
449449

450+
`Muhammad Haseeb Tariq <https://github.com/mhaseebtariq>`_ fixed issue #152, which made the whole interpreter hang on functions that launched an exception.
451+
450452
=========
451453
License
452454
=========

memory_profiler.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ def memory_usage(proc=-1, interval=.1, timeout=None, timestamps=False,
326326
raise ValueError
327327

328328
while True:
329+
exit_block = False
329330
child_conn, parent_conn = Pipe() # this will store MemTimer's results
330331
p = MemTimer(os.getpid(), interval, child_conn, backend,
331332
timestamps=timestamps,
@@ -338,23 +339,21 @@ def memory_usage(proc=-1, interval=.1, timeout=None, timestamps=False,
338339
# Therefore, the whole process hangs indefinitely. Here, we are ensuring that the process gets killed!
339340
try:
340341
returned = f(*args, **kw)
342+
parent_conn.send(0) # finish timing
343+
ret = parent_conn.recv()
344+
n_measurements = parent_conn.recv()
345+
if retval:
346+
ret = ret, returned
341347
except Exception:
342-
sys.stderr.write(traceback.format_exc())
343348
if has_psutil:
344349
parent = psutil.Process(os.getpid())
345350
for child in parent.children(recursive=True):
346351
os.kill(child.pid, SIGKILL)
347-
os.kill(os.getpid(), SIGKILL)
348-
else:
349-
sys.exit()
352+
p.join(0)
353+
raise
350354

351-
parent_conn.send(0) # finish timing
352-
ret = parent_conn.recv()
353-
n_measurements = parent_conn.recv()
354-
if retval:
355-
ret = ret, returned
356355
p.join(5 * interval)
357-
if n_measurements > 4 or interval < 1e-6:
356+
if exit_block or n_measurements > 4 or interval < 1e-6:
358357
break
359358
interval /= 10.
360359
elif isinstance(proc, subprocess.Popen):

test/test_exception.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
# make sure that memory profiler does not hang on exception
3+
from memory_profiler import memory_usage
4+
5+
def foo():
6+
raise NotImplementedError('Error')
7+
8+
try:
9+
out = memory_usage((foo, tuple(), {}), timeout=1)
10+
except NotImplementedError:
11+
pass
12+
print('Success')

0 commit comments

Comments
 (0)