# Buggy code
def begin_grading(
    self, submission: Submission, report=logger.info, blocking=False
) -> None:
    assert self.current_submission is None

    self.current_submission = submission
    ipc_ready_signal = threading.Event()
    grading_thread = threading.Thread(
        target=self._grading_thread_main,
        args=(ipc_ready_signal, submission, report),
        daemon=True,
    )
    grading_thread.start()

    ipc_ready_signal.wait()
    if blocking:
        grading_thread.join()


# Traceback (ConnectionResetError)
INFO 2020-07-04 08:30:53,248 54 judge Start grading atimesb/262720 in CPP11...
INFO 2020-07-04 08:30:53,261 54 packet Accept submission: 262720: executor: CPP11, code: atimesb
ERROR 2020-07-04 08:30:54,083 26503 judge Judge unexpectedly hung up!
Traceback (most recent call last):
File "/judge/dmoj/judge.py", line 350, in _ipc_recv_thread_main
ipc_type, data = judge_process_conn.recv()
File "/usr/lib/python3.8/multiprocessing/connection.py", line 250, in recv
buf = self._recv_bytes()
File "/usr/lib/python3.8/multiprocessing/connection.py", line 414, in _recv_bytes
buf = self._recv(4)
File "/usr/lib/python3.8/multiprocessing/connection.py", line 379, in _recv
chunk = read(handle, remaining)
ConnectionResetError: [Errno 104] Connection reset by peer
WARNING 2020-07-04 08:30:54,122 26503 tracer Skipping the killing of process because it already exited: 26515
ERROR 2020-07-04 08:30:54,122 54 judge Traceback (most recent call last):
File "/judge/dmoj/judge.py", line 151, in _grading_thread_main
handler_func(report, *data)
File "/judge/dmoj/judge.py", line 177, in _ipc_compile_message
self.packet_manager.compile_message_packet(compile_message)
File "/judge/dmoj/packet.py", line 324, in compile_message_packet
log.debug('Compile message: %d', self.judge.current_submission.id)
AttributeError: 'NoneType' object has no attribute 'id'
ERROR 2020-07-04 08:30:54,122 54 judge Error encountered while reporting error to site!
Traceback (most recent call last):
File "/judge/dmoj/judge.py", line 151, in _grading_thread_main
handler_func(report, *data)
File "/judge/dmoj/judge.py", line 177, in _ipc_compile_message
self.packet_manager.compile_message_packet(compile_message)
File "/judge/dmoj/packet.py", line 324, in compile_message_packet
log.debug('Compile message: %d', self.judge.current_submission.id)
AttributeError: 'NoneType' object has no attribute 'id'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/judge/dmoj/judge.py", line 267, in log_internal_error
self.packet_manager.internal_error_packet(strip_ansi(message))
File "/judge/dmoj/packet.py", line 330, in internal_error_packet
log.debug('Internal error: %d', self.judge.current_submission.id)
AttributeError: 'NoneType' object has no attribute 'id'
Process DMOJ Judge Handler for atimesb/262720:
Traceback (most recent call last):
File "/usr/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
self.run()
File "/usr/lib/python3.8/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/judge/dmoj/judge.py", line 371, in _worker_process_main
judge_process_conn.send(ipc_msg)
File "/usr/lib/python3.8/multiprocessing/connection.py", line 206, in send
self._send_bytes(_ForkingPickler.dumps(obj))
File "/usr/lib/python3.8/multiprocessing/connection.py", line 411, in _send_bytes
self._send(header + buf)
File "/usr/lib/python3.8/multiprocessing/connection.py", line 368, in _send
n = write(self._handle, buf)
BrokenPipeError: [Errno 32] Broken pipe

# Fixed code
def begin_grading(
    self, submission: Submission, report=logger.info, blocking=False
) -> None:
    # Ensure only one submission is running at a time; this lock is released at the end of submission grading.
    # This is necessary because `begin_grading` is "re-entrant"; after e.g. grading-end is sent, the network
    # thread may receive a new submission before the grading thread and worker from the *previous* submission
    # have finished tearing down. Trashing global state (e.g. `self.current_submission`) before then would be
    # an error.
    self._grading_lock.acquire()
    assert self.current_submission is None

    self.current_submission = submission
    ipc_ready_signal = threading.Event()
    grading_thread = threading.Thread(
        target=self._grading_thread_main,
        args=(ipc_ready_signal, submission, report),
        daemon=True,
    )
    grading_thread.start()

    ipc_ready_signal.wait()
    if blocking:
        grading_thread.join()