[Openmcl-devel] read-char-no-hang can hang
ron at flownet.com
Thu Nov 15 17:20:36 UTC 2012
SERIAL-STREAMS did the trick.
Just for the record, the device is a Teensy 3.0 (http://www.pjrc.com/store/teensy3.html). Its path is /dev/cu.usbmodem12341. CCL::%UNIX-FD-KIND returns :TTY, but OPEN does return a FILE-STREAM. I tried (open ... :class 'ccl::serial-stream) but that didn't work. Looks like that wouldn't be too hard to fix though.
On Nov 15, 2012, at 2:32 AM, Gary Byers wrote:
> On Wed, 14 Nov 2012, Ron Garret wrote:
>> When reading from /dev/some-slow-serial-device, read-char-no-hang can hang. I think this is because LISTEN is defined to return NIL only on EOF, and the OS doesn't report the absence of input characters as EOF. I tried to work around this by being devilishly clever and setting the underlying file descriptor to be non-blocking and using the FFI to call read() directly, but that seems to leave Lisp very confused:
>> ? (read-char f)
>>> Error: Expected newpos to be 3, fd is at 5
>>> While executing: CCL::IO-FILE-IOBLOCK-ADVANCE, in process Listener(6).
> That error message (and the reference to io-FILE-ioblock-advance) makes me think
> that F is a FILE-STREAM, and it's not clear to me that it should be. (One of the major differences between a FILE-STREAM and other kinds of fd-based streams
> is that the former is seekable and the latter isn't. I don't think of a stream
> associated with a serial device as being seekable, and I'm fairly sure that
> OPEN tries to return a non-seekable stream unless #_lseek seems to work on the fd.)
> (A FILE-STREAM open in direction :IO is a bit different from other kinds of streams
> that allow input and output: if you write an octet X to the stream (and it's likely
> just sitting in buffer for the time being), set the file-position back one octet
> and read an octet, you should get the same value (X) that you just wrote.) In non-FILE-streams, input and output are generally independent of each other. When
> they are related (in the FILE-STREAM case), some fairly simple things related to
> the file's position and length can be a little more compicated than they are
> otherwise (and you sometimes need to do FORCE-OUTPUT while reading, etc.) The
> error you got has to do with some consistency checks in that code and it's saying
> that the file's position isn't what we expect it to be, but serial devices don't
> have a (seekable) position.
> If FD is an open file descriptor, then (CCL::%UNIX-FD-KIND FD) will return a
> keyword that tries to (broadly) describe the underlying device. For an fd
> open to a serial device, it should return :TTY; I suspect that it returns something
> else in your example (you didn't OPEN a serial devices/TTY), or the stream was
> created as if you'd opened a (disk) file even though the serial devices is a different
> kind of animal.
> That's a mystery. Further mysteries include the device's baud rate, character
> size and framing, and all of the (often obscure) input, output, and other options
> that most of us likely haven't thought about (much) in a few decades.
> I'd certainly forgotten most of whatever I knew about this until a few
> years ago, when I needed to talk to a little testing device over a
> serial line (it was actually a USB-to-serial converter.) The code
> that was used to do that is in "ccl:library;serial-streams.lisp"; it
> doesn't do everything that you'd ever need to do to talk to an
> arbitrary serial device (remember modems ? Remember rs-232 signals
> like "Data Terminal Ready" ? Remember trying to guess which device is
> "DTE" and which is "DCE" ?), but it may be enough to get you started.
> (I just glanced at the code and noticed that it redefines a PRINT-OBJECT
> method on CCL::FD-STREAM; I think that it's more likely that the intent
> was to define a new method on CCL::SERIAL-STREAM. Whoever invented copy-and-paste
> had no idea how dangerous it could be in the wrong hands.)
>> Is there a way to reliably tell whether or not a call to read-char will hang on a serial device stream?
> I think that the most reliable way involves using #_poll or #_select
> with a timeout of 0; that'll return true if the fd is at EOF or if at
> least one octet can be read from the fd without blocking. (If that
> returns true, attempts to read more than 1 octet might block, and
> where the cutoff point is depends on the device and (possibly) on
> additional options. CCL::FD-INPUT-AVAILABLE-P (defined in
> "ccl:level-1;l1-streams.lisp") use #_poll to do this on Unix.
> A FILE-STREAM is assumed to never block (e.g, reading from it will always
> return some data or EOF immediately.) That may actually depend on the
> speed and reliability of the underlying filesystem, but I think that
> we generally assume that there's unread data available on a file stream
> if the position we'd read from is < the file's size. I haven't tried
> to hook up that USB-serial converter to another machine that actually has a serial port to test this, but I'd guess that the READ-CHAR-NO-HANG behavior
> you're seeing is related to the fact that the stream thinks it's closer to
> being a FILE-STREAM than it likely should be.
>> Openmcl-devel mailing list
>> Openmcl-devel at clozure.com
More information about the Openmcl-devel