On Thu, Apr 30, 2015 at 11:34:20PM -0400, Cody P Schafer wrote: > > > As I've said already, we *can't* set VMIN and use the kernel's support > > for this. To do that we would need to open the port without O_NONBLOCK, > > which would prevent sp_nonblocking_read() and sp_nonblocking_write) from > > working unless the port was reopened first. > > You're right, it becomes more tricky, and isn't a clear win. I hadn't > thought about needing to support both. > > Generally, fcntl() could be used to set/clear the O_NONBLOCK flag > without re-opening (assuming there isn't any race danger here), but > that's extra work on every read.
We've not yet formally documented anything about the thread-safety of libserialport functions, but my general feeling is that the policy should look like this: - Separate threads handling separate ports is OK. - Having separate "reader" and "writer" threads for the same port is OK - we'll define what that means more specifically but I think the concept is fairly obvious. Aside from concurrent read & write operations though, nothing should be called concurrently on the same port. With that approach, there's a definite race issue with using fcntl() to switch between blocking and non-blocking behaviour. > > So - I could add a function which has the semantics you want, but it > > would do exactly the same thing as calling sp_wait() followed by > > sp_nonblocking_read(). It would not actually set VMIN=1. Do you see that > > as worthwhile? > > I think it's a toss up. It's something I'd commonly use, so I'd > probably end up with a local impl (which would be similar to an > internal one) anyhow. I do see the argument for having a function with the semantics you're looking for. Let's try to pin down what it would look like so we have a clear proposal to discuss. How about this: sp_blocking_read_next(struct sp_port *port, void *buf, size_t count, unsigned int timeout_ms) Read bytes from the specified serial port, returning as soon any data is available. Parameters port Pointer to port structure. buf Buffer in which to store the bytes read. count Maximum number of bytes to read. Must not be zero. timeout_ms Timeout in milliseconds, or zero to wait indefinitely. Returns The number of bytes read, or a negative error code. If the result is zero, the timeout was reached before any bytes were available. If timeout_ms is zero, the function will always return either at least one byte, or a negative error code. Warning If your program runs on Unix, defines its own signal handlers, and needs to abort blocking reads when these are called, then you should not use this function. It repeats system calls that return with EINTR. To be able to abort a read from a signal handler, you should implement your own blocking read using sp_nonblocking_read() together with a blocking method that makes sense for your program. E.g. you can obtain the file descriptor for an open port using sp_get_port_handle() and use this to call select() or pselect(), with appropriate arrangements to return if a signal is received. The implementation would be as follows: POSIX: select() with the specified timeout_ms, but looped to handle EINTR. read() with specified buf and count, nonblocking due to O_NONBLOCK. Windows: SetCommTimeouts() with: ReadIntervalTimeout = MAXDWORD ReadTotalTimeoutMultiplier = MAXDWORD ReadTotalTimeoutConstant = timeout_ms ReadFile() with specified buf and count. One issue I see with this is how to handle the timeout_ms = 0 case on Windows. The VMIN=1 like behaviour described in the Remarks section of https://msdn.microsoft.com/en-us/library/windows/desktop/aa363190%28v=vs.85%29.aspx explicitly requires that ReadTotalTimeoutConstant be set to a value greater than 0 but less than MAXDWORD, implying a finite timeout. I do see a solution, though: if timeout_ms = 0, then set ReadTotalTimeoutConstant = MAXDWORD - 1. If the ReadFile call does time out, some 49.7 days later, it can just be repeated. What do you all think? Martin ------------------------------------------------------------------------------ One dashboard for servers and applications across Physical-Virtual-Cloud Widest out-of-the-box monitoring support with 50+ applications Performance metrics, stats and reports that give you Actionable Insights Deep dive visibility with transaction tracing using APM Insight. http://ad.doubleclick.net/ddm/clk/290420510;117567292;y _______________________________________________ sigrok-devel mailing list sigrok-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sigrok-devel