Skip to content

Commit

Permalink
clean abort on ctrl+c for fuzz
Browse files Browse the repository at this point in the history
  • Loading branch information
mzuenni committed May 20, 2024
1 parent ba5bcfa commit 413f251
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 6 deletions.
22 changes: 22 additions & 0 deletions bin/fuzz.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import generate
import time
import threading
from colorama import Fore, Style

import parallel
from util import *
Expand Down Expand Up @@ -184,6 +185,8 @@ def run(self):
error('No submissions found.')
return False

message('Press CTRL+C to stop\n', 'Fuzz', color_type=MessageType.LOG)

# config.args.no_bar = True
# max(len(s.name) for s in self.submissions)
bar = ProgressBar(f'Fuzz', max_len=60)
Expand All @@ -192,6 +195,21 @@ def run(self):
self.tasks = 0
self.queue = parallel.new_queue(lambda task: task.run(bar), pin=True)

def soft_exit(sig, frame):
if self.queue.aborted:
fatal('Running interrupted', force=True)
else:
self.queue.abort()
with bar:
bar.clearline()
message(
'Running interrupted (waiting on remaining tasks)\n',
'\nFuzz',
color_type=MessageType.ERROR,
)

signal.signal(signal.SIGINT, soft_exit)

# pool of ids used for generators
self.tmp_ids = 2 * max(1, self.queue.num_threads) + 1
self.free_tmp_id = {*range(self.tmp_ids)}
Expand All @@ -204,6 +222,10 @@ def run(self):
self.queue.join()
# At this point, no new tasks may be started anymore.
self.queue.done()

if self.queue.aborted:
fatal('Running interrupted', force=True)

bar.done()
bar.finalize()
return True
Expand Down
15 changes: 11 additions & 4 deletions bin/parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,15 @@ def _worker(self, cores: bool | list[int] = False):
def _interrupt_handler(self, sig, frame):
util.fatal('Running interrupted', force=True)

def _handle_first_error(self):
if self.first_error is not None:
first_error = self.first_error
self.first_error = None
# we are the main thread now, so we can handle this
if isinstance(first_error, ChildProcessError):
self._interrupt_handler(None, None)
raise first_error

# Add one task. Higher priority => done first
def put(self, task, priority=0):
with self.mutex:
Expand All @@ -180,8 +189,7 @@ def join(self):
# wait for all current task to be completed
with self.all_done:
self.all_done.wait_for(lambda: self.missing == 0)
if self.first_error:
raise self.first_error
self._handle_first_error()

# Wait for all tasks to be done and stop all threads
def done(self):
Expand All @@ -197,8 +205,7 @@ def done(self):

# mutex is no longer needed
# report first error occurred during execution
if self.first_error is not None:
raise self.first_error
self._handle_first_error()

# Discard all remaining work in the queue and stop all workers.
# Call done() to join the threads.
Expand Down
4 changes: 2 additions & 2 deletions bin/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ def is_bsd():

def exit1(force=False):
if force:
sys.stderr.close()
sys.stdout.close()
sys.stderr.close()
# exit even more forcefully to ensure that daemon threads dont break something
os._exit(1)
else:
Expand Down Expand Up @@ -1082,7 +1082,7 @@ def interrupt_handler(sig, frame):
# -2 corresponds to SIGINT, i.e. keyboard interrupt / CTRL-C.
if process.returncode == -2:
if threading.current_thread() is threading.main_thread():
fatal('Child process interrupted.')
fatal('Running interrupted')
else:
raise ChildProcessError()

Expand Down

0 comments on commit 413f251

Please sign in to comment.