I discovered a problem in the file drivers/serial/serial.c concerning the function uart_close(…). In the case that a serial device is opened with the flag O_NONBLOCK the function uart_close(…) blocks until all data in the buffer is transmitted. The function close(…) called on an handle opened with O_NONBLOCK should not block. The problem occurred with a CDC/ACM device.

This commit is contained in:
Stefan Kolb 2017-05-10 07:56:17 -06:00 committed by Gregory Nutt
parent 5b2ad3719c
commit 591f35be87
2 changed files with 21 additions and 16 deletions

View File

@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttX README Files</i></font></big></h1>
<p>Last Updated: April 18, 2017</p>
<p>Last Updated: May 9, 2017</p>
</td>
</tr>
</table>

View File

@ -1,7 +1,7 @@
/************************************************************************************
* drivers/serial/serial.c
*
* Copyright (C) 2007-2009, 2011-2013, 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2013, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -1207,26 +1207,31 @@ static int uart_close(FAR struct file *filep)
uart_disablerxint(dev);
/* Now we wait for the transmit buffer to clear */
/* Prevent blocking if the device is opened with O_NONBLOCK */
while (dev->xmit.head != dev->xmit.tail)
if ((filep->f_oflags & O_NONBLOCK) == 0)
{
#ifndef CONFIG_DISABLE_SIGNALS
usleep(HALF_SECOND_USEC);
#else
up_mdelay(HALF_SECOND_MSEC);
#endif
}
/* Now we wait for the transmit buffer to clear */
/* And wait for the TX fifo to drain */
while (!uart_txempty(dev))
{
while (dev->xmit.head != dev->xmit.tail)
{
#ifndef CONFIG_DISABLE_SIGNALS
usleep(HALF_SECOND_USEC);
usleep(HALF_SECOND_USEC);
#else
up_mdelay(HALF_SECOND_MSEC);
up_mdelay(HALF_SECOND_MSEC);
#endif
}
/* And wait for the TX fifo to drain */
while (!uart_txempty(dev))
{
#ifndef CONFIG_DISABLE_SIGNALS
usleep(HALF_SECOND_USEC);
#else
up_mdelay(HALF_SECOND_MSEC);
#endif
}
}
/* Free the IRQ and disable the UART */