Sockets in Lisp - sockets

I'm trying to communicate from a Lisp script to another program by using TCP/IP sockets (with sbcl and the usocket library in a Linux system). Through some online sources I have managed to put together the following simple code:
(require 'asdf)
(require 'usocket)
(defun start-client (message)
"Connects to server."
(usocket:with-client-socket (socket stream "0.0.0.0" 30000)
(format stream message)
(force-output stream)))
(start-client "Hello!~%")
This code lets me send a message, (I have tested it and it works). My problem is that I need to split this code in two different functions, one for opening the socket connection and another to send different messages at different times. Also I need to add an additional function to receive messages from the other program. However, as I'm quite new with Lisp I have failed to do so.

The best way (I think) would be to have your entire script in the scope of with-client-socket. You might have something like a main function where this would fit. This avoids resource leaks. You might want to use a dynamic variable to avoid passing the socket stream manually through function arguments to wherever it is needed.
Otherwise, you have to manage the closing of the socket yourself. Any call path that might lead to program termination needs to be protected by some unwind-protect that closes the socket using usocket:socket-close. For that, you open the socket using usocket:socket-connect with the same arguments as you used for usocket:with-client-socket. (You can take a look at the source for usocket:with-client-socket and usocket:with-connected-socket to see the interactions taking place.)
In order to be able to write to the socket stream (obtainable through (usocket:socket-stream socket)) and close the socket, you need to remember it somewhere, e. g. by binding a dynamic variable.

Related

Check if socket still open without blocking

How do I check if a TCP socket is still open without blocking?
If I am using usocket, then reading from a socket stream will signal end of file if the socket is closed, but will block it otherwise, which I don't want. I have tried using (listen stream) to check in advance if the socket will be blocked, but (listen) returns nil on a closed socket, which does not help here. I have also tried checking (usocket::state socket), which gives :READ on a closed socket, but it also sometimes gives :READ on an open socket even if there is not anything there. I am using sbcl, so I've tried using (sb-bsd-sockets:socket-open-p), but that gives T on a closed socket, also not helpful. The only command that seems to be helpful is (wait-for-input), namely it will return almost immediately when called on a closed socket, even when a longer timeout is given. At the same time, (listen) will still give nil, and that taken together seems to indicate a closed socket. This way looks rather hackish to me.
Is there a better way?
This isn't specifically a Lisp problem. It's a problem inherent to TCP itself.
The only way in TCP to tell if a connection is still open is to try to send data over it, or to use TCP's keepalive feature (which sends data over the socket for you).
Linux, Windows, and MacOS all have the SO_KEEPALIVE socket option (see setsockopt(2), which implements TCP keepalive. There are other associated sockopts, such as TCP_KEEPIDLE, TCP_KEEPINTVL, and TCP_KEEPCNT, but they aren't portable between operating systems, and in Lisp you'll have the added challenge of finding the actual values of the C preprocessor constants, and of providing a pointer for the option_value argument.
I haven't had any luck using SO_KEEPALIVE on Linux, and I haven't tried using it on any other operating system.
It's a bug in SBCL. The stream you get from (usocket:socket-stream s) and the one you get from calling cl:open are of the same type, so they behave the same way.
You get the correct behavior if you close a stream using cl:close:
(with-open-file (in "/dev/zero" :element-type '(unsigned-byte 8))
(close in)
(listen in))
And that correct behavior is an error. (On SBCL the type of the error is SB-INT:CLOSED-STREAM-ERROR)
If you simulate the other end of a socket closing by closing the underlying file descriptor with a POSIX call, you get the same NIL return value as with a real socket:
(with-open-file (in "/dev/zero" :element-type '(unsigned-byte 8))
(sb-posix:close (slot-value in 'sb-impl::fd))
(listen in)) ;; NIL
Whatever listen is doing is failing to notice that the underlying file descriptor is closed.
The blocking behavior is also identical:
(with-open-file (in "/dev/zero" :element-type '(unsigned-byte 8))
(sb-posix:close (slot-value in 'sb-impl::fd))
(read-byte in)) ;; hangs, Emacs interrupt doesn't work
In the source code for listen, I saw comments that claim that select(2) is used to implement listen, but I couldn't find the actual call to select. That call to select, if it's happening, is returning -1, and errno is not being consulted to find out why. It's likely that the -1 return code is being missed.
This affects the latest version of SBCL that Debian ships, but I don't know about the latest released version of SBCL.

Common Lisp: flush standard output

Trying to learn lisp (and I guess emacs along with it).
I was wondering how you would go about clearing the output and replacing it.
Could be in a LISP repl, or an emacs buffer.
Something akin to the following in python.
def go(r):
for i in range(r):
sys.stdout.write("\rDoing %i" % i)
sys.stdout.flush()
For common lisp, you are looking for
Functions FINISH-OUTPUT, FORCE-OUTPUT, CLEAR-OUTPUT:
finish-output, force-output, and clear-output exercise control over the internal handling of buffered stream output.
finish-output attempts to ensure that any buffered output sent to output-stream has reached its destination, and then returns.
force-output initiates the emptying of any internal buffers but does not wait for completion or acknowledgment to return.
clear-output attempts to abort any outstanding output operation in progress in order to allow as little output as possible to continue to the destination.
and
Variables *DEBUG-IO*, *ERROR-OUTPUT*, *QUERY-IO*, *STANDARD-INPUT*, *STANDARD-OUTPUT*, *TRACE-OUTPUT*
The value of *debug-io*, called debug I/O, is a stream to be used for interactive debugging purposes.
The value of *error-output*, called error output, is a stream to which warnings and non-interactive error messages should be sent.
The value of *query-io*, called query I/O, is a bidirectional stream to be used when asking questions of the user. The question should be output to this stream, and the answer read from it.
The value of *standard-input*, called standard input, is a stream that is used by many operators as a default source of input when no specific input stream is explicitly supplied.
The value of *standard-output*, called standard output, is a stream that is used by many operators as a default destination for output when no specific output stream is explicitly supplied.
The value of *trace-output*, called trace output, is the stream on which traced functions (see trace) and the time macro print their output.
Emacs Lisp is quite different, you might want to start here: https://www.gnu.org/software/emacs/manual/html_node/elisp/Output-Functions.html

Named pipe similar to "mkfifo" creation, but bidirectional

I'd like to create a named pipe, like the one created by "mkfifo", but one caveat. I want the pipe to be bidirectional. That is, I want process A to write to the fifo, and process B to read from it, and vice-versa. A pipe created by "mkfifo" allows process A to read the data its written to the pipe. Normally I'd use two pipes, but I am trying to simulate an actual device so I'd like the semantics of open(), read(), write(), etc to be as similar to the actual device as possible. Anyone know of a technique to accomplish this without resorting to two pipes or a named socket?
Or pty ("pseudo-terminal interface"). man pty.
Use a Unix-domain socket.
Oh, you said you don't want to use the only available solution - a Unix-domain socket.
In that case, you are stuck with opening two named pipes, or doing without. Or write your own device driver for them, of course - you could do it for the open source systems, anyway; it might be harder for the closed source systems (Windows, AIX, HP-UX).

Why does writing to an unconnected socket send SIGPIPE first?

There are so many possible errors in the POSIX environment. Why do some of them (like writing to an unconnected socket in particular) get special treatment in the form of signals?
This is by design, so that simple programs producing text (e.g. find, grep, cat) used in a pipeline would die when their consumer dies. That is, if you're running a chain like find | grep | sed | head, head will exit as soon as it reads enough lines. That will kill sed with SIGPIPE, which will kill grep with SIGPIPE, which will kill find with SEGPIPE. If there were no SIGPIPE, naively written programs would continue running and producing content that nobody needs.
If you don't want to get SIGPIPE in your program, just ignore it with a call to signal(). After that, syscalls like write() that hit a broken pipe will return with errno=EPIPE instead.
See this SO answer for a detailed explanation of why writing a closed descriptor / socket generates SIGPIPE.
Why is writing a closed TCP socket worse than reading one?
SIGPIPE isn't specific to sockets — as the name would suggest, it is also sent when you try to write to a pipe (anonymous or named) as well. I guess the reason for having separate error-handling behaviour is that broken pipes shouldn't always be treated as an error (whereas, for example, trying to write to a file that doesn't exist should always be treated as an error).
Consider the program less. This program reads input from stdin (unless a filename is specified) and only shows part of it at a time. If the user scrolls down, it will try to read more input from stdin, and display that. Since it doesn't read all the input at once, the pipe will be broken if the user quits (e.g. by pressing q) before the input has all been read. This isn't really a problem, though, so the program that's writing down the pipe should handle it gracefully.
it's up to the design.
at the beginning people use signal to control events notification which were sent to the user space, and later it is not necessary because there're more popular skeletons such as polling which don't require a system caller to make a signal handler.

AllegroServe on SBCL 1.0.28 failing with `accept invalid keyword argument: :AUTO-CLOSE`

New version of SBCL 1.0.28 running on debian breaks AllegroServe 1.2.47 on incoming connection with following error:
aserve-accept-6: 05/26/09 - 21:11:01 - accept: error 0 on accept invalid
keyword argument: :AUTO-CLOSE (valid keys are
:INPUT, :OUTPUT, :ELEMENT-TYPE, :EXTERNAL-FORMAT,
:BUFFERING, :TIMEOUT).
Portable AllegroServe page does make a mention of this problem. However, no google searches turn up anything of use for this problem.
Any ideas as to how to move forward with this problem, or alternatively, links pointing to places where this has been dealt with?
After some mucking around, I've come up with the following solution:
In my source files, after I declare my package, compile/load the appropriate modules but before I declare anything in my package, I added the following code:
(defmethod sb-bsd-sockets:socket-make-stream ((socket sb-bsd-sockets:socket)
&key input output
(element-type 'character)
(buffering :full)
(external-format :default)
timeout
(auto-close t))
"Default method for SOCKET objects. An ELEMENT-TYPE of :DEFAULT
will construct a bivalent stream. Acceptable values for BUFFERING
are :FULL, :LINE and :NONE. Streams will have no TIMEOUT
by default.
The stream for SOCKET will be cached, and a second invocation of this
method will return the same stream. This may lead to oddities if this
function is invoked with inconsistent arguments \(e.g., one might request
an input stream and get an output stream in response\)."
(let ((stream
(and (slot-boundp socket 'stream) (slot-value socket 'stream))))
(unless stream
(setf stream (sb-sys:make-fd-stream
(sb-bsd-sockets:socket-file-descriptor socket)
:name "a socket"
:dual-channel-p t
:input input
:output output
:element-type element-type
:buffering buffering
:external-format external-format
:timeout timeout
:auto-close auto-close)))
(setf (slot-value socket 'stream) stream)
(sb-ext:cancel-finalization socket)
stream))
(It's basically a lift from what is in the sb-bsd-sockets/socket.lisp with the auto-close key added to the argument list)
This way I avoid modifying or patching system files, and basically hook into the sb-bsd-sockets package directly.
So far, it seems to be working as it should. Basic testing via successive calls to (room) shows me that there's no obvious memory leaks, and the performance is as expected.
Please feel free to comment on this kludge, and if you think it might affect the stability of my system in unexpected ways.