SBCL doesn't use O_NOCTTY
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Won't Fix
|
Undecided
|
Unassigned |
Bug Description
For whatever reason, probably having to do with the getty(8) and login(8) programs, the ancients decided that on Unix, if you open a serial device and you don't have a controlling terminal, this serial device becomes your controlling terminal.
SBCL inherits this behavior when it runs on Unix, because it implements CL:OPEN using the POSIX function open(2), and it doesn't pass the SB-UNIX:O_NOCTTY flag. Furthermore, there is no flag you can pass to CL:OPEN to get it to supply the flag, and it doesn't matter if you open a character or a binary stream.
I ran into the consequences of this recently when I wrote a daemon in Lisp that communicates with an Arduino board through a binary stream opened on the /dev/ttyACM0 device Linux registers for it when it is plugged in. Everything worked fine when I developed the app under SLIME. Then I bundled it up with SAVE-LISP-AND-DIE, and wrote a Systemd service file to launch it on boot.
When run from Systemd, the program didn't work, and for a long time I had no idea why.
The reason why was because the Arduino connection was being turned into a controlling terminal. Because the connection is now a terminal, Linux filters all the data through the line discipline. Certain bytes are interpreted as triggering actions, instead of being sent directly to the program on the other end. So when the Arduino sends #x8, that gets interpreted as a backspace. And #x13 pauses output. And so on.
I was forced to implement a Gray stream which behaves just like normal streams, except when I create an instance of it I open the file descriptor using the O_NOCTTY flag.
I encountered this problem using SBCL 1.4.16.debian, but the I can see that the bug is still there in GitHub. The sb-unix:o_noctty constant is nowhere to be found:
https:/
I think you are using the wrong API to access the serial device. To communicate with a device on a serial port you may need to set the baud rate, turn off line buffering or character echoing, set parity, etc. You want a lower level API than Common Lisp streams, an API that supports ioctl operations on the file descriptor you have opened. Perhaps the file APIs in the SB-POSIX contrib package will work. The symbol SB-POSIX:O-NOCTTY is bound in my copy of SBCL.
A possible workaround that might allow you to use standard streams ... After opening the device, perhaps a TIOCNOTTY ioctl on the stream's file descriptor will cause your process to lose its controlling terminal.