function eventloop(socket) task_local_storage(:IJulia_task, "write task") try while true msg = recv_ipython(socket) try send_status("busy", msg) invokelatest(handlers[msg.header["msg_type"]], socket, msg) catch e # Try to keep going if we get an exception, but # send the exception traceback to the front-ends. # (Ignore SIGINT since this may just be a user-requested # kernel interruption to interrupt long calculations.) if !isa(e, InterruptException) content = error_content(e, msg="KERNEL EXCEPTION") map(s -> println(orig_stderr[], s), content["traceback"]) send_ipython(publish[], msg_pub(execute_msg, "error", content)) end finally flush_all() send_status("idle", msg) end end catch e # the Jupyter manager may send us a SIGINT if the user # chooses to interrupt the kernel; don't crash on this if isa(e, InterruptException) eventloop(socket) else rethrow() end end end const requests_task = Ref{Task}() function waitloop() @async eventloop(control[]) requests_task[] = @async eventloop(requests[]) while true try wait() catch e # send interrupts (user SIGINT) to the code-execution task if isa(e, InterruptException) @async Base.throwto(requests_task[], e) else rethrow() end end end end