diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-08-12 17:37:04 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-08-12 17:37:04 +0000 |
commit | 4d7cbe088ed6ea14adc0672b339f1e0df4650f00 (patch) | |
tree | b8701e6c319c085758d39c4dd7d08c380fc2088a | |
parent | 66fcc36c58e7670ef627985cc37ac99dc747c02f (diff) | |
download | nuttx-4d7cbe088ed6ea14adc0672b339f1e0df4650f00.tar.gz nuttx-4d7cbe088ed6ea14adc0672b339f1e0df4650f00.tar.bz2 nuttx-4d7cbe088ed6ea14adc0672b339f1e0df4650f00.zip |
drivers/serial/serial.c open, read, write, and poll methods will not return a short transfer or an EINTR error if a signal is received while waiting (only)
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5022 42af7a65-404d-4744-a932-0658087f49c3
-rwxr-xr-x | apps/ChangeLog.txt | 2 | ||||
-rw-r--r-- | apps/system/readline/readline.c | 50 | ||||
-rw-r--r-- | nuttx/ChangeLog | 4 | ||||
-rw-r--r-- | nuttx/TODO | 19 | ||||
-rw-r--r-- | nuttx/drivers/serial/serial.c | 217 | ||||
-rw-r--r-- | nuttx/include/netinet/arp.h | 19 | ||||
-rw-r--r-- | nuttx/include/nuttx/net/ioctl.h | 1 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_libfwrite.c | 2 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_lowinstream.c | 17 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_lowoutstream.c | 5 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_meminstream.c | 13 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_memoutstream.c | 6 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_nullinstream.c | 5 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_nulloutstream.c | 3 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_rawinstream.c | 34 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_rawoutstream.c | 29 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_stdinstream.c | 25 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_stdoutstream.c | 24 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_syslogstream.c | 30 |
19 files changed, 385 insertions, 120 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt index 1bb2a08b5..37d05bacd 100755 --- a/apps/ChangeLog.txt +++ b/apps/ChangeLog.txt @@ -274,3 +274,5 @@ no arguments outputs a short list of commands. With -v lists all command line details. And command name can be added to just get help on one command. + * system/readline.c: If character input/output is interrupted by a + signal, then readline() will try the read/write again. diff --git a/apps/system/readline/readline.c b/apps/system/readline/readline.c index f7fa6a635..bdd39e67b 100644 --- a/apps/system/readline/readline.c +++ b/apps/system/readline/readline.c @@ -103,13 +103,34 @@ static inline int readline_rawgetc(int infd) char buffer; ssize_t nread; - nread = read(infd, &buffer, 1); - if (nread < 1) + /* Loop until we successfully read a character (or until an unexpected + * error occurs). + */ + + do { - /* Return EOF if the end of file (0) or error (-1) occurs */ + /* Read one character from the incoming stream */ + + nread = read(infd, &buffer, 1); + + /* Return EOF if the end of file (0) or error (-1) occurs. */ + + if (nread < 1) + { + /* EINTR is not really an error; it simply means that a signal we + * received while watiing for intput. + */ - return EOF; + if (nread == 0 || errno != EINTR) + { + return EOF; + } + } } + while (nread < 1); + + /* On success, returnt he character that was read */ + return (int)buffer; } @@ -121,7 +142,26 @@ static inline int readline_rawgetc(int infd) static inline void readline_consoleputc(int ch, int outfd) { char buffer = ch; - (void)write(outfd, &buffer, 1); + ssize_t nwritten; + + /* Loop until we successfully write a character (or until an unexpected + * error occurs). + */ + + do + { + /* Write the character to the outgoing stream */ + + nwritten = write(outfd, &buffer, 1); + + /* Check for irrecoverable write errors. */ + + if (nwritten < 0 && errno != EINTR) + { + break; + } + } + while (nwritten < 1); } #endif diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 364de21a3..78a6323dd 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -3154,3 +3154,7 @@ * arch/arm/src/stm32/stm32f2xx_dma.c and stm32f4xx_dma.c: Backed out the DMA priority change just above. The reduced SD card frequency was necessary and sufficient to resolve the problem. + * drivers/serial/serial.c: open, read, write, and poll methods may now + abort return EINTR (or a short transfer size) if a signal is received + while waiting to receive or send serial data. This behavior is required + by POSIX. diff --git a/nuttx/TODO b/nuttx/TODO index f9fc558ea..543d15f70 100644 --- a/nuttx/TODO +++ b/nuttx/TODO @@ -1,4 +1,4 @@ -NuttX TODO List (Last updated August 7, 2012) +NuttX TODO List (Last updated August 12, 2012) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with @@ -16,7 +16,7 @@ nuttx/ (17) Network (net/, drivers/net) (3) USB (drivers/usbdev, drivers/usbhost) (11) Libraries (lib/) - (10) File system/Generic drivers (fs/, drivers/) + (9) File system/Generic drivers (fs/, drivers/) (5) Graphics subystem (graphics/) (1) Pascal add-on (pcode/) (1) Documentation (Documentation/) @@ -750,21 +750,6 @@ o File system / Generic drivers (fs/, drivers/) Status: Open Priority: Low - Title: SERIAL DRIVER DOES NOT RETURN WHEN SIGNAL RECEIVED - Description: The serial driver (drivers/serial) should return with an - error and errno=EINTR when an interrupt is received. However, - the serial driver just continues waiting: - - static void uart_takesem(FAR sem_t *sem) - { - while (sem_wait(sem) != 0) - { - ASSERT(*get_errno_ptr() == EINTR); - } - } - Status: Open - Priority Medium - Title: POLLHUP SUPPORT Description: All drivers that support the poll method should also report POLLHUP event when the driver is closedd. diff --git a/nuttx/drivers/serial/serial.c b/nuttx/drivers/serial/serial.c index e0bd6dc0b..c0ebd245a 100644 --- a/nuttx/drivers/serial/serial.c +++ b/nuttx/drivers/serial/serial.c @@ -112,16 +112,29 @@ static const struct file_operations g_serialops = * Name: uart_takesem ************************************************************************************/ -static void uart_takesem(FAR sem_t *sem) +static int uart_takesem(FAR sem_t *sem, bool errout) { - while (sem_wait(sem) != 0) + /* Loop, ignoring interrupts, until we have successfully acquired the semaphore */ + + while (sem_wait(sem) != OK) { - /* The only case that an error should occur here is if - * the wait was awakened by a signal. + /* The only case that an error should occur here is if the wait was awakened + * by a signal. */ ASSERT(get_errno() == EINTR); + + /* When the signal is received, should we errout? Or should we just continue + * waiting until we have the semaphore? + */ + + if (errout) + { + return -EINTR; + } } + + return OK; } /************************************************************************************ @@ -161,10 +174,11 @@ static void uart_pollnotify(FAR uart_dev_t *dev, pollevent_t eventset) * Name: uart_putxmitchar ************************************************************************************/ -static void uart_putxmitchar(FAR uart_dev_t *dev, int ch) +static int uart_putxmitchar(FAR uart_dev_t *dev, int ch) { irqstate_t flags; int nexthead; + int ret; /* Increment to see what the next head pointer will be. We need to use the "next" * head pointer to determine when the circular buffer would overrun @@ -184,29 +198,43 @@ static void uart_putxmitchar(FAR uart_dev_t *dev, int ch) { dev->xmit.buffer[dev->xmit.head] = ch; dev->xmit.head = nexthead; - return; + return OK; } else { - /* Inform the interrupt level logic that we are waiting. - * This and the following steps must be atomic. + /* Inform the interrupt level logic that we are waiting. This and + * the following steps must be atomic. */ flags = irqsave(); dev->xmitwaiting = true; - /* Wait for some characters to be sent from the buffer - * with the TX interrupt enabled. When the TX interrupt - * is enabled, uart_xmitchars should execute and remove - * some of the data from the TX buffer. + /* Wait for some characters to be sent from the buffer with the TX + * interrupt enabled. When the TX interrupt is enabled, uart_xmitchars + * should execute and remove some of the data from the TX buffer. */ uart_enabletxint(dev); - uart_takesem(&dev->xmitsem); + ret = uart_takesem(&dev->xmitsem, true); uart_disabletxint(dev); irqrestore(flags); + + /* Check if we were awakened by signal. */ + + if (ret < 0) + { + /* A signal received while waiting for the xmit buffer to become + * non-full will abort the transfer. + */ + + return -EINTR; + } } } + + /* We won't get here */ + + return OK; } /************************************************************************************ @@ -241,9 +269,10 @@ static ssize_t uart_irqwrite(FAR uart_dev_t *dev, FAR const char *buffer, size_t static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t buflen) { - FAR struct inode *inode = filep->f_inode; - FAR uart_dev_t *dev = inode->i_private; - ssize_t ret = buflen; + FAR struct inode *inode = filep->f_inode; + FAR uart_dev_t *dev = inode->i_private; + ssize_t nread = buflen; + int ret; /* We may receive console writes through this path from * interrupt handlers and from debug output in the IDLE task! @@ -266,9 +295,18 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t } } - /* Only one user can be accessing dev->xmit.head at once */ + /* Only one user can access dev->xmit.head at a time */ - uart_takesem(&dev->xmit.sem); + ret = (ssize_t)uart_takesem(&dev->xmit.sem, true); + if (ret < 0) + { + /* A signal received while waiting for access to the xmit.head will + * abort the transfer. After the transfer has started, we are committed + * and signals will be ignored. + */ + + return ret; + } /* Loop while we still have data to copy to the transmit buffer. * we add data to the head of the buffer; uart_xmitchars takes the @@ -280,15 +318,50 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t { int ch = *buffer++; + /* If this is the console, then we should replace LF with CR-LF */ + + ret = OK; + if (dev->isconsole && ch == '\n') + { + ret = uart_putxmitchar(dev, '\r'); + } + /* Put the character into the transmit buffer */ - uart_putxmitchar(dev, ch); + if (ret == OK) + { + ret = uart_putxmitchar(dev, ch); + } - /* If this is the console, then we should replace LF with LF-CR */ + /* Were we awakened by a signal? That should be the only condition that + * uart_putxmitchar() should return an error. + */ - if (dev->isconsole && ch == '\n') + if (ret < 0) { - uart_putxmitchar(dev, '\r'); + /* POSIX requires that we return -1 and errno set if no data was + * transferred. Otherwise, we return the number of bytes in the + * interrupted transfer. + */ + + if (buflen < nread) + { + /* Some data was transferred. Return the number of bytes that were + * successfully transferred. + */ + + nread -= buflen; + } + else + { + /* No data was transferred. Return -EINTR. The VFS layer will + * set the errno value appropriately). + */ + + nread = -EINTR; + } + + break; } } @@ -298,7 +371,7 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t } uart_givesem(&dev->xmit.sem); - return ret; + return nread; } /************************************************************************************ @@ -312,10 +385,20 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen irqstate_t flags; ssize_t recvd = 0; int16_t tail; + int ret; - /* Only one user can be accessing dev->recv.tail at once */ + /* Only one user can access dev->recv.tail at a time */ - uart_takesem(&dev->recv.sem); + ret = uart_takesem(&dev->recv.sem, true); + if (ret < 0) + { + /* A signal received while waiting for access to the recv.tail will avort + * the transfer. After the transfer has started, we are committed and + * signals will be ignored. + */ + + return ret; + } /* Loop while we still have data to copy to the receive buffer. * we add data to the head of the buffer; uart_xmitchars takes the @@ -352,6 +435,7 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen { tail = 0; } + dev->recv.tail = tail; } @@ -426,12 +510,34 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen uart_enablerxint(dev); /* Now wait with the Rx interrupt re-enabled. NuttX will - * automatically re-enable global interrupts when this - * thread goes to sleep. + * automatically re-enable global interrupts when this thread + * goes to sleep. */ - uart_takesem(&dev->recvsem); + ret = uart_takesem(&dev->recvsem, true); irqrestore(flags); + + /* Was a signal received while waiting for data to be received? */ + + if (ret < 0) + { + /* POSIX requires that we return after a signal is received. + * If some bytes were read, we need to return the number of bytes + * read; if no bytes were read, we need to return -1 with the + * errno set correctly. + */ + + if (recvd == 0) + { + /* No bytes were read, return -EINTR (the VFS layer will + * set the errno value appropriately. + */ + + recvd = -EINTR; + } + + break; + } } else { @@ -472,7 +578,7 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) FAR uart_dev_t *dev = inode->i_private; pollevent_t eventset; int ndx; - int ret = OK; + int ret; int i; /* Some sanity checking */ @@ -486,7 +592,16 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) /* Are we setting up the poll? Or tearing it down? */ - uart_takesem(&dev->pollsem); + ret = uart_takesem(&dev->pollsem, true); + if (ret < 0) + { + /* A signal received while waiting for access to the poll data + * will abort the operation. + */ + + return ret; + } + if (setup) { /* This is a request to set up the poll. Find an available @@ -514,31 +629,43 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) goto errout; } - /* Should immediately notify on any of the requested events? + /* Should we immediately notify on any of the requested events? * First, check if the xmit buffer is full. + * + * Get exclusive access to the xmit buffer indices. NOTE: that we do not + * let this wait be interrupted by a signal (we probably should, but that + * would be a little awkward). */ eventset = 0; + (void)uart_takesem(&dev->xmit.sem, false); - uart_takesem(&dev->xmit.sem); ndx = dev->xmit.head + 1; if (ndx >= dev->xmit.size) { ndx = 0; } + if (ndx != dev->xmit.tail) { eventset |= POLLOUT; } + uart_givesem(&dev->xmit.sem); - /* Check if the receive buffer is empty */ + /* Check if the receive buffer is empty + * + * Get exclusive access to the recv buffer indices. NOTE: that we do not + * let this wait be interrupted by a signal (we probably should, but that + * would be a little awkward). + */ - uart_takesem(&dev->recv.sem); + (void)uart_takesem(&dev->recv.sem, false); if (dev->recv.head != dev->recv.tail) { eventset |= POLLIN; } + uart_givesem(&dev->recv.sem); if (eventset) @@ -588,7 +715,13 @@ static int uart_close(FAR struct file *filep) FAR uart_dev_t *dev = inode->i_private; irqstate_t flags; - uart_takesem(&dev->closesem); + /* Get exclusive access to the close semaphore (to synchronize open/close operations. + * NOTE: that we do not let this wait be interrupted by a signal. Technically, we + * should, but almost no one every checks the return value from close() so we avoid + * a potential memory leak by ignoring signals in this case. + */ + + (void)uart_takesem(&dev->closesem, false); if (dev->open_count > 1) { dev->open_count--; @@ -653,11 +786,19 @@ static int uart_open(FAR struct file *filep) struct inode *inode = filep->f_inode; uart_dev_t *dev = inode->i_private; uint8_t tmp; - int ret = OK; + int ret; - /* If the port is the middle of closing, wait until the close is finished */ + /* If the port is the middle of closing, wait until the close is finished. + * If a signal is received while we are waiting, then return EINTR. + */ + + ret = uart_takesem(&dev->closesem, true); + if (ret < 0) + { + /* A signal received while waiting for the last close operation. */ - uart_takesem(&dev->closesem); + return ret; + } /* Start up serial port */ /* Increment the count of references to the device. */ diff --git a/nuttx/include/netinet/arp.h b/nuttx/include/netinet/arp.h index 34cfc84a4..e318945aa 100644 --- a/nuttx/include/netinet/arp.h +++ b/nuttx/include/netinet/arp.h @@ -58,14 +58,17 @@ #define SIOCDARP _ARPIOC(2) /* Delete an ARP mapping */ #define SIOCGARP _ARPIOC(3) /* Get an ARP mapping */ -/* Values for the FLAGS field in struct arpreq */ - -#define ATF_COM 0x01 /* Lookup complete */ -#define ATF_PERM 0x02 /* Permanent entry */ -#define ATF_PUBL 0x04 /* Publish entry */ -#define ATF_USETRAILERS 0x10 /* Trailers requested */ -#define ATF_NETMASK 0x20 /* Use a netmask */ -#define ATF_DONTPUB 0x40 /* Don't answer */ +/* Definitions for bits in field arp_flags of struct arpreq. If the + * ATF_NETMASK flag is set, then arp_netmask should be valid. This should + * be set to 0xffffffff, or 0 to remove an existing arp entry. + */ + +#define ATF_COM (1 << 0) /* Lookup complete */ +#define ATF_PERM (1 << 1) /* Permanent entry */ +#define ATF_PUBL (1 << 2) /* Publish entry */ +#define ATF_USETRAILERS (1 << 3) /* Trailers requested (obsolete) */ +#define ATF_NETMASK (1 << 4) /* Use a netmask */ +#define ATF_DONTPUB (1 << 5) /* Don't answer */ /**************************************************************************** * Public Type Definitions diff --git a/nuttx/include/nuttx/net/ioctl.h b/nuttx/include/nuttx/net/ioctl.h index 5bce5eaf1..be3f597f4 100644 --- a/nuttx/include/nuttx/net/ioctl.h +++ b/nuttx/include/nuttx/net/ioctl.h @@ -149,6 +149,7 @@ /**************************************************************************** * Type Definitions ****************************************************************************/ +/* See include/net/if.h */ /**************************************************************************** * Public Function Prototypes diff --git a/nuttx/lib/stdio/lib_libfwrite.c b/nuttx/lib/stdio/lib_libfwrite.c index e2c35e3e9..e71866b49 100644 --- a/nuttx/lib/stdio/lib_libfwrite.c +++ b/nuttx/lib/stdio/lib_libfwrite.c @@ -2,7 +2,7 @@ * lib/stdio/lib_libfwrite.c * * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/nuttx/lib/stdio/lib_lowinstream.c b/nuttx/lib/stdio/lib_lowinstream.c index 6dcc4a37e..c97a4721f 100644 --- a/nuttx/lib/stdio/lib_lowinstream.c +++ b/nuttx/lib/stdio/lib_lowinstream.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_lowinstream.c * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -42,7 +42,9 @@ #ifdef CONFIG_ARCH_LOWGETC #include <stdio.h> +#include <assert.h> #include <errno.h> + #include <nuttx/arch.h> #include "lib_internal.h" @@ -57,10 +59,19 @@ static int lowinstream_getc(FAR struct lib_instream_s *this) { - if (this && up_getc(ch) != EOF) + int ret; + + DEBUGASSERT(this); + + /* Get the next character from the incoming stream */ + + ret = up_getc(ch) + if (ret != EOF) { this->nget++; } + + return ret; } /**************************************************************************** diff --git a/nuttx/lib/stdio/lib_lowoutstream.c b/nuttx/lib/stdio/lib_lowoutstream.c index 726bd84d7..092f39ca2 100644 --- a/nuttx/lib/stdio/lib_lowoutstream.c +++ b/nuttx/lib/stdio/lib_lowoutstream.c @@ -42,6 +42,7 @@ #ifdef CONFIG_ARCH_LOWPUTC #include <stdio.h> +#include <assert.h> #include <errno.h> #include <nuttx/arch.h> @@ -57,7 +58,9 @@ static void lowoutstream_putc(FAR struct lib_outstream_s *this, int ch) { - if (this && up_putc(ch) != EOF) + DEBUGASSERT(this); + + if (up_putc(ch) != EOF) { this->nput++; } diff --git a/nuttx/lib/stdio/lib_meminstream.c b/nuttx/lib/stdio/lib_meminstream.c index 839e56219..a842096fb 100644 --- a/nuttx/lib/stdio/lib_meminstream.c +++ b/nuttx/lib/stdio/lib_meminstream.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_meminstream.c * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,8 @@ * Included Files ****************************************************************************/ +#include <assert.h> + #include "lib_internal.h" /**************************************************************************** @@ -52,7 +54,11 @@ static int meminstream_getc(FAR struct lib_instream_s *this) FAR struct lib_meminstream_s *mthis = (FAR struct lib_meminstream_s *)this; int ret; - if (this && this->nget < mthis->buflen) + DEBUGASSERT(this); + + /* Get the next character (if any) from the buffer */ + + if (this->nget < mthis->buflen) { ret = mthis->buffer[this->nget]; this->nget++; @@ -61,6 +67,7 @@ static int meminstream_getc(FAR struct lib_instream_s *this) { ret = EOF; } + return ret; } diff --git a/nuttx/lib/stdio/lib_memoutstream.c b/nuttx/lib/stdio/lib_memoutstream.c index 007ab8976..21197358b 100644 --- a/nuttx/lib/stdio/lib_memoutstream.c +++ b/nuttx/lib/stdio/lib_memoutstream.c @@ -37,6 +37,8 @@ * Included Files ****************************************************************************/ +#include <assert.h> + #include "lib_internal.h" /**************************************************************************** @@ -51,12 +53,14 @@ static void memoutstream_putc(FAR struct lib_outstream_s *this, int ch) { FAR struct lib_memoutstream_s *mthis = (FAR struct lib_memoutstream_s *)this; + DEBUGASSERT(this); + /* If this will not overrun the buffer, then write the character to the * buffer. Not that buflen was pre-decremented when the stream was * created so it is okay to write past the end of the buflen by one. */ - if (this && this->nput < mthis->buflen) + if (this->nput < mthis->buflen) { mthis->buffer[this->nput] = ch; this->nput++; diff --git a/nuttx/lib/stdio/lib_nullinstream.c b/nuttx/lib/stdio/lib_nullinstream.c index 271cba396..0eadb0a8e 100644 --- a/nuttx/lib/stdio/lib_nullinstream.c +++ b/nuttx/lib/stdio/lib_nullinstream.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_nullinstream.c * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -39,6 +39,7 @@ #include <stdio.h> #include <errno.h> + #include "lib_internal.h" /**************************************************************************** diff --git a/nuttx/lib/stdio/lib_nulloutstream.c b/nuttx/lib/stdio/lib_nulloutstream.c index 520df459e..69878fd57 100644 --- a/nuttx/lib/stdio/lib_nulloutstream.c +++ b/nuttx/lib/stdio/lib_nulloutstream.c @@ -38,7 +38,9 @@ ****************************************************************************/ #include <stdio.h> +#include <assert.h> #include <errno.h> + #include "lib_internal.h" /**************************************************************************** @@ -47,6 +49,7 @@ static void nulloutstream_putc(FAR struct lib_outstream_s *this, int ch) { + DEBUGASSERT(this); this->nput++; } diff --git a/nuttx/lib/stdio/lib_rawinstream.c b/nuttx/lib/stdio/lib_rawinstream.c index ead3116b4..aacc8f867 100644 --- a/nuttx/lib/stdio/lib_rawinstream.c +++ b/nuttx/lib/stdio/lib_rawinstream.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_rawinstream.c * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,7 +38,9 @@ ****************************************************************************/ #include <unistd.h> +#include <assert.h> #include <errno.h> + #include "lib_internal.h" /**************************************************************************** @@ -52,23 +54,27 @@ static int rawinstream_getc(FAR struct lib_instream_s *this) { FAR struct lib_rawinstream_s *rthis = (FAR struct lib_rawinstream_s *)this; + int nwritten; char ch; - if (this && rthis->fd >= 0) + DEBUGASSERT(this && rthis->fd >= 0); + + /* Attempt to read one character */ + + nwritten = read(rthis->fd, &ch, 1); + if (nwritten == 1) { - int nwritten; - do - { - nwritten = read(rthis->fd, &ch, 1); - if (nwritten == 1) - { - this->nget++; - return ch; - } - } - while (nwritten < 0 && get_errno() == EINTR); + this->nget++; + return ch; } + /* Return EOF on any failure to read from the incoming byte stream. The + * only expected error is EINTER meaning that the read was interrupted + * by a signal. A Zero return value would indicated an end-of-file + * confition. + */ + + DEBUGASSERT(nwritten == 0 || get_errno() == EINTR); return EOF; } diff --git a/nuttx/lib/stdio/lib_rawoutstream.c b/nuttx/lib/stdio/lib_rawoutstream.c index ce9d33280..b4a20958b 100644 --- a/nuttx/lib/stdio/lib_rawoutstream.c +++ b/nuttx/lib/stdio/lib_rawoutstream.c @@ -38,7 +38,9 @@ ****************************************************************************/ #include <unistd.h> +#include <assert.h> #include <errno.h> + #include "lib_internal.h" /**************************************************************************** @@ -52,19 +54,28 @@ static void rawoutstream_putc(FAR struct lib_outstream_s *this, int ch) { FAR struct lib_rawoutstream_s *rthis = (FAR struct lib_rawoutstream_s *)this; + int nwritten; char buffer = ch; - if (this && rthis->fd >= 0) + + DEBUGASSERT(this && rthis->fd >= 0); + + /* Loop until the character is successfully transferred */ + + for (;;) { - int nwritten; - do + nwritten = write(rthis->fd, &buffer, 1); + if (nwritten == 1) { - nwritten = write(rthis->fd, &buffer, 1); - if (nwritten == 1) - { - this->nput++; - } + this->nput++; + return; } - while (nwritten < 0 && get_errno() == EINTR); + + /* The only expected error is EINTR, meaning that the write operation + * was awakened by a signal. Zero would not be a valid return value + * either. + */ + + DEBUGASSERT(nwritten < 0 && get_errno() == EINTR); } } diff --git a/nuttx/lib/stdio/lib_stdinstream.c b/nuttx/lib/stdio/lib_stdinstream.c index d89b6b63a..77aab9ec8 100644 --- a/nuttx/lib/stdio/lib_stdinstream.c +++ b/nuttx/lib/stdio/lib_stdinstream.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_stdinstream.c * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,8 @@ * Included Files ****************************************************************************/ +#include <assert.h> + #include "lib_internal.h" /**************************************************************************** @@ -50,16 +52,19 @@ static int stdinstream_getc(FAR struct lib_instream_s *this) { FAR struct lib_stdinstream_s *sthis = (FAR struct lib_stdinstream_s *)this; - if (this) + int ret; + + DEBUGASSERT(this); + + /* Get the next character from the incoming stream */ + + ret = getc(sthis->stream); + if (ret != EOF) { - int ret = getc(sthis->stream); - if (ret != EOF) - { - this->nget++; - } - return ret; + this->nget++; } - return EOF; + + return ret; } /**************************************************************************** diff --git a/nuttx/lib/stdio/lib_stdoutstream.c b/nuttx/lib/stdio/lib_stdoutstream.c index 12e78ce53..b8dd0bf63 100644 --- a/nuttx/lib/stdio/lib_stdoutstream.c +++ b/nuttx/lib/stdio/lib_stdoutstream.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_stdoutstream.c * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,6 +38,8 @@ ****************************************************************************/ #include <fcntl.h> +#include <assert.h> +#include <errno.h> #include "lib_internal.h" @@ -52,12 +54,26 @@ static void stdoutstream_putc(FAR struct lib_outstream_s *this, int ch) { FAR struct lib_stdoutstream_s *sthis = (FAR struct lib_stdoutstream_s *)this; - if (this) + int result; + + DEBUGASSERT(this && sthis->stream); + + /* Loop until the character is successfully transferred */ + + for (;;) { - if (putc(ch, sthis->stream) != EOF) + result = fputc(ch, sthis->stream); + if (result != EOF) { this->nput++; + return; } + + /* EINTR (meaning that fputc was interrupted by a signal) is the only + * expected error. + */ + + DEBUGASSERT(get_errno() == EINTR); } } diff --git a/nuttx/lib/stdio/lib_syslogstream.c b/nuttx/lib/stdio/lib_syslogstream.c index 20c6165ca..1a47f6abb 100644 --- a/nuttx/lib/stdio/lib_syslogstream.c +++ b/nuttx/lib/stdio/lib_syslogstream.c @@ -40,6 +40,7 @@ #include <nuttx/config.h> #include <unistd.h> +#include <assert.h> #include <errno.h> #include <nuttx/syslog.h> @@ -62,10 +63,31 @@ static void syslogstream_putc(FAR struct lib_outstream_s *this, int ch) { - /* Write the character to the supported logging device */ - - (void)syslog_putc(ch); - this->nput++; + int ret; + + /* Try writing until the write was successful or until an irrecoverable + * error occurs. + */ + + for (;;) + { + /* Write the character to the supported logging device */ + + ret = syslog_putc(ch); + if (ret == OK) + { + this->nput++; + return; + } + + /* On failure syslog_putc will return a negated errno value. The + * errno variable will not be set. The special value -EINTR means that + * syslog_putc() was awakened by a signal. This is not a real error and + * must be ignored in this context. + */ + + DEBUGASSERT(ret == -EINTR); + } } /**************************************************************************** |