# Buggy code
def _grading_thread_main(
    self, ipc_ready_signal: threading.Event, submission: Submission, report
) -> None:
    try:
        report(
            ansi_style(
                "Start grading #ansi[%s](yellow)/#ansi[%s](green|bold) in %s..."
                % (submission.problem_id, submission.id, submission.language)
            )
        )

        self.current_judge_worker = JudgeWorker(submission)

        ipc_handler_dispatch: Dict[IPC, Callable] = {
            IPC.HELLO: lambda _report: ipc_ready_signal.set(),
            IPC.COMPILE_ERROR: self._ipc_compile_error,
            IPC.COMPILE_MESSAGE: self._ipc_compile_message,
            IPC.GRADING_BEGIN: self._ipc_grading_begin,
            IPC.GRADING_END: self._ipc_grading_end,
            IPC.GRADING_ABORTED: self._ipc_grading_aborted,
            IPC.BATCH_BEGIN: self._ipc_batch_begin,
            IPC.BATCH_END: self._ipc_batch_end,
            IPC.RESULT: self._ipc_result,
            IPC.UNHANDLED_EXCEPTION: self._ipc_unhandled_exception,
        }

        for ipc_type, data in self.current_judge_worker.communicate():
            try:
                handler_func = ipc_handler_dispatch[ipc_type]
            except KeyError:
                raise RuntimeError(
                    "judge got unexpected IPC message from worker: %s"
                    % ((ipc_type, data),)
                ) from None

            handler_func(report, *data)

        report(
            ansi_style(
                "Done grading #ansi[%s](yellow)/#ansi[%s](green|bold).\n"
                % (submission.problem_id, submission.id)
            )
        )
    except Exception:  # noqa: E722, we want to catch everything
        self.log_internal_error()
    finally:
        if self.current_judge_worker is not None:
            self.current_judge_worker.stop()

        self.current_submission = None
        self.current_judge_worker = None

        # Might not have been set if an exception was encountered before HELLO message, so signal here to keep the
        # other side from waiting forever.
        ipc_ready_signal.set()

        self._grading_lock.release()


# Traceback (AttributeError)
INFO 2020-07-15 17:02:08,535 56 judge Start grading boi2019p3/2205852 in CPP11...
INFO 2020-07-15 17:02:08,540 56 packet Accept submission: 2205852: executor: CPP11, code: boi2019p3
INFO 2020-07-15 17:02:09,336 56 judge Batch #1
INFO 2020-07-15 17:02:09,346 56 judge   Test case  1 AC [0.002s (0.003s) | 5668kb]
INFO 2020-07-15 17:02:09,356 56 judge   Test case  2 AC [0.003s (0.004s) | 5348kb]
INFO 2020-07-15 17:02:09,357 56 judge Batch #2
INFO 2020-07-15 17:02:09,376 56 judge   Test case  3 AC [0.011s (0.012s) | 5672kb]
INFO 2020-07-15 17:02:09,395 56 judge   Test case  4 WA [0.011s (0.012s) | 5104kb]
INFO 2020-07-15 17:02:09,395 56 judge   Test case  5 --
INFO 2020-07-15 17:02:09,395 56 judge   Test case  6 --
INFO 2020-07-15 17:02:09,396 56 judge Batch #3
INFO 2020-07-15 17:02:09,409 56 judge   Test case  7 WA [0.006s (0.008s) | 5860kb]
INFO 2020-07-15 17:02:09,409 56 judge   Test case  8 --
INFO 2020-07-15 17:02:09,410 56 judge   Test case  9 --
INFO 2020-07-15 17:02:09,410 56 judge   Test case 10 --
INFO 2020-07-15 17:02:09,425 56 judge   Test case 11 --
INFO 2020-07-15 17:02:09,425 56 judge   Test case 12 --
INFO 2020-07-15 17:02:09,426 56 judge   Test case 13 --
INFO 2020-07-15 17:02:09,426 56 judge   Test case 14 --
INFO 2020-07-15 17:02:09,426 56 judge   Test case 15 --
INFO 2020-07-15 17:02:09,426 56 judge   Test case 16 --
INFO 2020-07-15 17:02:09,426 56 judge Batch #4
WARNING 2020-07-15 17:02:14,456 19004 tracer Shocker activated and killed 19036
WARNING 2020-07-15 17:02:14,456 19004 tracer Request the killing of process: 19036
INFO 2020-07-15 17:02:14,458 56 judge   Test case 17 TLE [5.000s (5.001s) | 12368kb] {RTE, WA}
INFO 2020-07-15 17:02:14,458 56 judge   Test case 18 --
INFO 2020-07-15 17:02:14,461 56 judge   Test case 19 --
INFO 2020-07-15 17:02:14,462 56 judge   Test case 20 --
INFO 2020-07-15 17:02:14,465 56 judge   Test case 21 --
INFO 2020-07-15 17:02:14,466 56 judge   Test case 22 --
INFO 2020-07-15 17:02:14,471 56 judge Batch #5
INFO 2020-07-15 17:02:14,478 56 packet Received abortion request for 2205852
WARNING 2020-07-15 17:02:14,479 19004 tracer Skipping the killing of process because it already exited: 19036
ERROR 2020-07-15 17:02:19,481 56 judge Worker is still alive, sending SIGKILL!
ERROR 2020-07-15 17:02:19,484 56 judge Failed to read IPC message from worker!
ERROR 2020-07-15 17:02:19,497 56 judge Traceback (most recent call last):
File "/judge/dmoj/judge.py", line 152, in _grading_thread_main
for ipc_type, data in self.current_judge_worker.communicate():
File "/judge/dmoj/judge.py", line 306, in communicate
ipc_type, data = self.worker_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 383, in _recv
raise EOFError
EOFError

ERROR 2020-07-15 17:02:19,628 56 packet Exception while reading packet from site, will not attempt to reconnect! Quitting judge.
Traceback (most recent call last):
File "/judge/dmoj/packet.py", line 156, in _read_forever
self._receive_packet(self._read_single())
File "/judge/dmoj/packet.py", line 276, in _receive_packet
log.info('Received abortion request for %s', self.judge.current_submission.id)
AttributeError: 'NoneType' object has no attribute 'id'

# Fixed code
def _grading_thread_main(self, ipc_ready_signal: threading.Event, report) -> None:
    assert self.current_judge_worker is not None

    try:
        ipc_handler_dispatch: Dict[IPC, Callable] = {
            IPC.HELLO: lambda _report: ipc_ready_signal.set(),
            IPC.COMPILE_ERROR: self._ipc_compile_error,
            IPC.COMPILE_MESSAGE: self._ipc_compile_message,
            IPC.GRADING_BEGIN: self._ipc_grading_begin,
            IPC.GRADING_END: self._ipc_grading_end,
            IPC.GRADING_ABORTED: self._ipc_grading_aborted,
            IPC.BATCH_BEGIN: self._ipc_batch_begin,
            IPC.BATCH_END: self._ipc_batch_end,
            IPC.RESULT: self._ipc_result,
            IPC.UNHANDLED_EXCEPTION: self._ipc_unhandled_exception,
        }

        for ipc_type, data in self.current_judge_worker.communicate():
            try:
                handler_func = ipc_handler_dispatch[ipc_type]
            except KeyError:
                raise RuntimeError(
                    "judge got unexpected IPC message from worker: %s"
                    % ((ipc_type, data),)
                ) from None

            handler_func(report, *data)

        report(
            ansi_style(
                "Done grading #ansi[%s](yellow)/#ansi[%s](green|bold).\n"
                % (self.current_submission.problem_id, self.current_submission.id)
            )
        )
    except Exception:  # noqa: E722, we want to catch everything
        self.log_internal_error()
    finally:
        self.current_judge_worker.stop()

        with self._current_submission_lock:
            self.current_judge_worker = None

        # Might not have been set if an exception was encountered before HELLO message, so signal here to keep the
        # other side from waiting forever.
        ipc_ready_signal.set()

        self._grading_lock.release()