Show More
@@ -466,10 +466,9 b' class AuthenticatedZMQStreamHandler(ZMQStreamHandler):' | |||||
466 | class IOPubHandler(AuthenticatedZMQStreamHandler): |
|
466 | class IOPubHandler(AuthenticatedZMQStreamHandler): | |
467 |
|
467 | |||
468 | def initialize(self, *args, **kwargs): |
|
468 | def initialize(self, *args, **kwargs): | |
469 | self._kernel_alive = True |
|
|||
470 | self._beating = False |
|
|||
471 | self.iopub_stream = None |
|
469 | self.iopub_stream = None | |
472 | self.hb_stream = None |
|
470 | self.hb_stream = None | |
|
471 | self.heartbeat = None | |||
473 |
|
472 | |||
474 | def on_first_message(self, msg): |
|
473 | def on_first_message(self, msg): | |
475 | try: |
|
474 | try: | |
@@ -478,12 +477,13 b' class IOPubHandler(AuthenticatedZMQStreamHandler):' | |||||
478 | self.close() |
|
477 | self.close() | |
479 | return |
|
478 | return | |
480 | km = self.application.kernel_manager |
|
479 | km = self.application.kernel_manager | |
481 | self.time_to_dead = km.time_to_dead |
|
|||
482 | self.first_beat = km.first_beat |
|
|||
483 | kernel_id = self.kernel_id |
|
480 | kernel_id = self.kernel_id | |
484 | try: |
|
481 | try: | |
485 | self.iopub_stream = km.create_iopub_stream(kernel_id) |
|
482 | self.iopub_stream = km.create_iopub_stream(kernel_id) | |
486 | self.hb_stream = km.create_hb_stream(kernel_id) |
|
483 | self.hb_stream = km.create_hb_stream(kernel_id) | |
|
484 | self.heartbeat = Heartbeat( | |||
|
485 | stream=self.hb_stream, config=self.application.config | |||
|
486 | ) | |||
487 | except web.HTTPError: |
|
487 | except web.HTTPError: | |
488 | # WebSockets don't response to traditional error codes so we |
|
488 | # WebSockets don't response to traditional error codes so we | |
489 | # close the connection. |
|
489 | # close the connection. | |
@@ -492,7 +492,7 b' class IOPubHandler(AuthenticatedZMQStreamHandler):' | |||||
492 | self.close() |
|
492 | self.close() | |
493 | else: |
|
493 | else: | |
494 | self.iopub_stream.on_recv(self._on_zmq_reply) |
|
494 | self.iopub_stream.on_recv(self._on_zmq_reply) | |
495 |
self.start |
|
495 | self.heartbeat.start(self.kernel_died) | |
496 |
|
496 | |||
497 | def on_message(self, msg): |
|
497 | def on_message(self, msg): | |
498 | pass |
|
498 | pass | |
@@ -507,51 +507,7 b' class IOPubHandler(AuthenticatedZMQStreamHandler):' | |||||
507 | self.iopub_stream.close() |
|
507 | self.iopub_stream.close() | |
508 | if self.hb_stream is not None and not self.hb_stream.closed(): |
|
508 | if self.hb_stream is not None and not self.hb_stream.closed(): | |
509 | self.hb_stream.close() |
|
509 | self.hb_stream.close() | |
510 |
|
510 | # stop the heartbeat here | ||
511 | def start_hb(self, callback): |
|
|||
512 | """Start the heartbeating and call the callback if the kernel dies.""" |
|
|||
513 | if not self._beating: |
|
|||
514 | self._kernel_alive = True |
|
|||
515 |
|
||||
516 | def ping_or_dead(): |
|
|||
517 | self.hb_stream.flush() |
|
|||
518 | if self._kernel_alive: |
|
|||
519 | self._kernel_alive = False |
|
|||
520 | self.hb_stream.send(b'ping') |
|
|||
521 | # flush stream to force immediate socket send |
|
|||
522 | self.hb_stream.flush() |
|
|||
523 | else: |
|
|||
524 | try: |
|
|||
525 | callback() |
|
|||
526 | except: |
|
|||
527 | pass |
|
|||
528 | finally: |
|
|||
529 | self.stop_hb() |
|
|||
530 |
|
||||
531 | def beat_received(msg): |
|
|||
532 | self._kernel_alive = True |
|
|||
533 |
|
||||
534 | self.hb_stream.on_recv(beat_received) |
|
|||
535 | loop = ioloop.IOLoop.instance() |
|
|||
536 | self._hb_periodic_callback = ioloop.PeriodicCallback(ping_or_dead, self.time_to_dead*1000, loop) |
|
|||
537 | loop.add_timeout(time.time()+self.first_beat, self._really_start_hb) |
|
|||
538 | self._beating= True |
|
|||
539 |
|
||||
540 | def _really_start_hb(self): |
|
|||
541 | """callback for delayed heartbeat start |
|
|||
542 |
|
||||
543 | Only start the hb loop if we haven't been closed during the wait. |
|
|||
544 | """ |
|
|||
545 | if self._beating and not self.hb_stream.closed(): |
|
|||
546 | self._hb_periodic_callback.start() |
|
|||
547 |
|
||||
548 | def stop_hb(self): |
|
|||
549 | """Stop the heartbeating and cancel all related callbacks.""" |
|
|||
550 | if self._beating: |
|
|||
551 | self._beating = False |
|
|||
552 | self._hb_periodic_callback.stop() |
|
|||
553 | if not self.hb_stream.closed(): |
|
|||
554 | self.hb_stream.on_recv(None) |
|
|||
555 |
|
511 | |||
556 | def _delete_kernel_data(self): |
|
512 | def _delete_kernel_data(self): | |
557 | """Remove the kernel data and notebook mapping.""" |
|
513 | """Remove the kernel data and notebook mapping.""" |
@@ -22,6 +22,7 b' from IPython.kernel.multikernelmanager import MultiKernelManager' | |||||
22 | from IPython.utils.traitlets import ( |
|
22 | from IPython.utils.traitlets import ( | |
23 | Dict, List, Unicode, Float, Integer, |
|
23 | Dict, List, Unicode, Float, Integer, | |
24 | ) |
|
24 | ) | |
|
25 | ||||
25 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
26 | # Classes |
|
27 | # Classes | |
27 | #----------------------------------------------------------------------------- |
|
28 | #----------------------------------------------------------------------------- |
General Comments 0
You need to be logged in to leave comments.
Login now