Skip to content

Commit 8b30876

Browse files
authored
[Debugger Plugin] Exit TensorBoard on SIGINT even with debugger enabled (#975)
* [Debugger Plugin] Exit TensorBoard on SIGINT even with debugger enabled
1 parent dad4df9 commit 8b30876

File tree

3 files changed

+46
-18
lines changed

3 files changed

+46
-18
lines changed

Diff for: tensorboard/plugins/debugger/README.md

+18-7
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ This dashboard is in its **alpha release**. Some features are not yet fully func
1616

1717
To enable the debugger dashboard, pass the `debugger_port` flag to TensorBoard. TensorBoard will then both receive gRPC messages from and issue gRPC messages to model logic via this port.
1818

19-
This command demonstrates how to set the debugger port to 6064.
19+
This command demonstrates how to set the debugger port to 6064.
2020

2121
```
2222
tensorboard \
@@ -166,10 +166,21 @@ For example, suppose a tensor has a shape of (500, 100), applying a slicing of `
166166

167167
For each tensor, the time axis (history of the tensor's execution) is treated as an 1D array. Numpy-style slicing can be applied to time. For example, the default slicing of `-1` selects the most recent value. However, if the user changes that slicing parameter to `:`, the full history of the tensor will be shown (and the rank of the tensor being visualized is increased by 1).
168168

169-
# Limitations
169+
# Frequently Asked Questions (FAQ)
170170

171-
* Hitting Ctrl+C (issuing a SIGINT signal) might fail to terminate execution for a model that is instrumented with
172-
`TensorBoardDebugWrapperSession` or its corresponding hook. The same limitation may be present in the tensorboard
173-
process as well. In those cases, the user must manually
174-
[kill](https://www.linux.com/learn/intro-to-linux/2017/5/how-kill-process-command-line) the processes.
175-
* The debugger dashboard does not yet support multiple users debugging at once.
171+
## Q: How to exit debugging?
172+
173+
Answer: Follow these steps to interrupt your TensorFlow program being debugged
174+
and the TensorBoard process running the debugger plugin (*in that order*):
175+
176+
1. Send `SIGINT` to the TensorFlow program being debugged, e.g., by using
177+
`Ctrl+C`.
178+
2. Send `SIGINT` to the TensorBoard process running the debugger plugin, e.g.,
179+
by using `Ctrl+C`.
180+
181+
# Limitations and Known Issues
182+
183+
The debugger plugin has the following limitations and known issues. We plan to
184+
fix them in future releases.
185+
186+
* The debugger plugin does not yet support multiple users debugging at once.

Diff for: tensorboard/plugins/debugger/interactive_debugger_plugin.py

+28-2
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020

2121
import json
2222
import platform
23+
import signal
2324
import sys
2425
import threading
2526

27+
from six.moves import xrange # pylint:disable=redefined-builtin
2628
import tensorflow as tf
2729
from werkzeug import wrappers
2830

@@ -69,6 +71,7 @@ def __init__(self, context):
6971
"""
7072
del context # Unused.
7173
self._debugger_data_server = None
74+
self._server_thread = None
7275
self._grpc_port = None
7376

7477
def listen(self, grpc_port):
@@ -96,8 +99,31 @@ def listen(self, grpc_port):
9699
interactive_debugger_server_lib.InteractiveDebuggerDataServer(
97100
self._grpc_port))
98101

99-
threading.Thread(target=self._debugger_data_server.
100-
start_the_debugger_data_receiving_server).start()
102+
self._server_thread = threading.Thread(
103+
target=self._debugger_data_server.run_server)
104+
self._server_thread.start()
105+
106+
signal.signal(signal.SIGINT, self.signal_handler)
107+
# Note: this is required because of a wontfix issue in grpc/python 2.7:
108+
# https://github.com/grpc/grpc/issues/3820
109+
110+
def signal_handler(self, unused_signal, unused_frame):
111+
if self._debugger_data_server and self._server_thread:
112+
print('Stopping InteractiveDebuggerPlugin...')
113+
# Enqueue a number of messages to the incoming message queue to try to
114+
# let the debugged tensorflow runtime proceed past the current Session.run
115+
# in the C++ layer and return to the Python layer, so the SIGINT handler
116+
# registered there may be triggered.
117+
for _ in xrange(len(self._debugger_data_server.breakpoints) + 1):
118+
self._debugger_data_server.put_incoming_message(True)
119+
try:
120+
self._debugger_data_server.stop_server()
121+
except ValueError:
122+
# In case the server has already stopped running.
123+
pass
124+
self._server_thread.join()
125+
print('InteractiveDebuggerPlugin stopped.')
126+
sys.exit(0)
101127

102128
def get_plugin_apps(self):
103129
"""Obtains a mapping between routes and handlers.

Diff for: tensorboard/plugins/debugger/interactive_debugger_server_lib.py

-9
Original file line numberDiff line numberDiff line change
@@ -515,15 +515,6 @@ def __init__(self, receive_port):
515515
grpc_debug_server.EventListenerBaseServicer.__init__(
516516
self, receive_port, curried_handler_constructor)
517517

518-
def start_the_debugger_data_receiving_server(self):
519-
"""Starts the HTTP server for receiving health pills at `receive_port`.
520-
521-
After this method is called, health pills issued to host:receive_port
522-
will be stored by this object. Calling this method also creates a file
523-
within the log directory for storing health pill summary events.
524-
"""
525-
self.run_server()
526-
527518
def SendTracebacks(self, request, context):
528519
self._source_manager.add_graph_traceback(request.graph_version,
529520
request.graph_traceback)

0 commit comments

Comments
 (0)