From 2c827b218813f2663fc3fb09d2ad61f50c4ec1ff Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 27 Nov 2013 14:31:54 +0000 Subject: [PATCH] Handle EINTR from tcdrain() in sp_drain(). --- libserialport.h.in | 7 +++++++ serialport.c | 22 ++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/libserialport.h.in b/libserialport.h.in index 46e2fda..41948c1 100644 --- a/libserialport.h.in +++ b/libserialport.h.in @@ -878,6 +878,13 @@ enum sp_return sp_flush(struct sp_port *port, enum sp_buffer buffers); /** * Wait for buffered data to be transmitted. * + * @warning If your program runs on Unix, defines its own signal handlers, and + * needs to abort draining the output buffer when 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 drain from a + * signal handler, you would need to implement your own blocking + * drain by polling the result of sp_output_waiting(). + * * @param port Pointer to port structure. * * @return SP_OK upon success, a negative error code otherwise. diff --git a/serialport.c b/serialport.c index 51eda87..bbb53bd 100644 --- a/serialport.c +++ b/serialport.c @@ -799,13 +799,23 @@ enum sp_return sp_drain(struct sp_port *port) /* Returns non-zero upon success, 0 upon failure. */ if (FlushFileBuffers(port->hdl) == 0) RETURN_FAIL("FlushFileBuffers() failed"); -#else - /* Returns 0 upon success, -1 upon failure. */ - if (tcdrain(port->fd) < 0) - RETURN_FAIL("tcdrain() failed"); -#endif - RETURN_OK(); +#else + int result; + while (1) { + result = tcdrain(port->fd); + if (result < 0) { + if (errno == EINTR) { + DEBUG("tcdrain() was interrupted"); + continue; + } else { + RETURN_FAIL("tcdrain() failed"); + } + } else { + RETURN_OK(); + } + } +#endif } enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, size_t count, unsigned int timeout)