Skip to content

Commit 4fe60d3

Browse files
committed
remote debugging
1 parent 42067a3 commit 4fe60d3

File tree

2 files changed

+113
-3
lines changed

2 files changed

+113
-3
lines changed

content/building-blocks/deployment.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,3 @@ threads, requests per second,…).
153153

154154
See [cl-sentry-client](https://github.com/mmontone/cl-sentry-client/) for error reporting.
155155

156-
## Connecting to a remote Lisp image (Swank server)
157-
158-
See this Cookbook section: [debugging#remote-debugging](https://lispcookbook.github.io/cl-cookbook/debugging.html#remote-debugging).
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
+++
2+
title = "Remote debugging"
3+
weight = 205
4+
+++
5+
6+
You can have your software running on a machine over the network,
7+
connect to it and debug it from home, from your development
8+
environment.
9+
10+
You can not only inspect the running program, but also compile and
11+
load new code, including installing new libraries, effectively doing
12+
hot code reload. It's up to you to decide to do it or to follow the
13+
industry's best practices. It isn't because you use Common Lisp that
14+
you have to make your deployed program a "big ball of mud".
15+
16+
Also don't be too afraid, because when you connect to the remote
17+
application from your development machine and start writing code, you
18+
are writing code on your local files, in your git project. When you
19+
compile and load it with the usual shortcuts (C-c C-c), you are
20+
sending the changes to the remote app.
21+
22+
TLDR; local changes, remote execution.
23+
24+
25+
{{% notice info %}}
26+
We are re-using content we contributed to the Cookbook.
27+
{{% /notice %}}
28+
29+
The steps involved are to start a **Swank server** on the remote machine (Swank is the backend companion of Slime), create an
30+
ssh tunnel and connect to the Swank server from our editor. Then we
31+
can browse and evaluate code on the running instance transparently.
32+
33+
To test this, let's define a function that prints forever.
34+
35+
If needed, import the dependencies first:
36+
37+
~~~lisp
38+
(ql:quickload '("swank" "bordeaux-threads"))
39+
~~~
40+
41+
42+
~~~lisp
43+
;; a little common lisp swank demo
44+
;; while this program is running, you can connect to it from
45+
;; another terminal or machine
46+
;; and change the definition of doprint to print something else out!
47+
48+
(require :swank)
49+
(require :bordeaux-threads)
50+
51+
(defparameter *counter* 0)
52+
53+
(defun dostuff ()
54+
(format t "hello world ~a!~%" *counter*))
55+
56+
(defun runner ()
57+
(swank:create-server :port 4006 :dont-close t)
58+
(format t "we are past go!~%")
59+
(bt:make-thread (lambda ()
60+
(loop repeat 5 do
61+
(sleep 5)
62+
(dostuff)
63+
(incf *counter*)))
64+
:name "do-stuff"))
65+
66+
(runner)
67+
~~~
68+
69+
On the server, we can run this code with
70+
71+
sbcl --load demo.lisp
72+
73+
If you check with `(bt:all-threads)`, you'll see your Swank server running on port 4006, as well
74+
as the other thread ready to do stuff:
75+
76+
(#<SB-THREAD:THREAD "do-stuff" RUNNING {10027CEDC3}>
77+
#<SB-THREAD:THREAD "Swank Sentinel" waiting on:
78+
#<WAITQUEUE {10027D0003}>
79+
{10027CE8B3}>
80+
#<SB-THREAD:THREAD "Swank 4006" RUNNING {10027CEB63}>
81+
#<SB-THREAD:THREAD "main thread" RUNNING {1007C40393}>)
82+
83+
We do port forwarding on our development machine:
84+
85+
ssh -L4006:127.0.0.1:4006 [email protected]
86+
87+
this will securely forward port 4006 on the server at example.com to
88+
our local computer's port 4006 (Swank only accepts connections from
89+
localhost).
90+
91+
We connect to the running Swank with `M-x slime-connect`, choosing localhost for the host
92+
and port 4006.
93+
94+
We can write new code:
95+
96+
~~~lisp
97+
(defun dostuff ()
98+
(format t "goodbye world ~a!~%" *counter*))
99+
(setf *counter* 0)
100+
~~~
101+
102+
and eval it as usual with `C-c C-c` or `M-x slime-eval-region` for instance. The output should change.
103+
104+
That's how Ron Garret debugged the Deep Space 1 spacecraft from the earth
105+
in 1999:
106+
107+
> We were able to debug and fix a race condition that had not shown up during ground testing. (Debugging a program running on a $100M piece of hardware that is 100 million miles away is an interesting experience. Having a read-eval-print loop running on the spacecraft proved invaluable in finding and fixing the problem.
108+
109+
## References
110+
111+
- [Slime documentation: connecting to a remote Lisp](https://common-lisp.net/project/slime/doc/html/Connecting-to-a-remote-lisp.html#Connecting-to-a-remote-lisp)
112+
- [Ron Garret: Lisping at the JPL](http://www.flownet.com/gat/jpl-lisp.html#1994-1999%20-%20Remote%20Agent)
113+
- [CL Cookbook: debugging](https://lispcookbook.github.io/cl-cookbook/debugging.html)

0 commit comments

Comments
 (0)