9
0
Fork 0

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: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@5022 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2012-08-12 17:37:04 +00:00
parent 84b540ddad
commit 0ac24568a7
19 changed files with 386 additions and 121 deletions

View File

@ -274,3 +274,5 @@
no arguments outputs a short list of commands. With -v lists all no arguments outputs a short list of commands. With -v lists all
command line details. And command name can be added to just get command line details. And command name can be added to just get
help on one command. help on one command.
* system/readline.c: If character input/output is interrupted by a
signal, then readline() will try the read/write again.

View File

@ -103,13 +103,34 @@ static inline int readline_rawgetc(int infd)
char buffer; char buffer;
ssize_t nread; ssize_t nread;
nread = read(infd, &buffer, 1); /* Loop until we successfully read a character (or until an unexpected
if (nread < 1) * error occurs).
{ */
/* Return EOF if the end of file (0) or error (-1) occurs */
return EOF; do
{
/* 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.
*/
if (nread == 0 || errno != EINTR)
{
return EOF;
}
}
} }
while (nread < 1);
/* On success, returnt he character that was read */
return (int)buffer; return (int)buffer;
} }
@ -121,7 +142,26 @@ static inline int readline_rawgetc(int infd)
static inline void readline_consoleputc(int ch, int outfd) static inline void readline_consoleputc(int ch, int outfd)
{ {
char buffer = ch; 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 #endif

View File

@ -3154,3 +3154,7 @@
* arch/arm/src/stm32/stm32f2xx_dma.c and stm32f4xx_dma.c: Backed out the * 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 DMA priority change just above. The reduced SD card frequency was
necessary and sufficient to resolve the problem. 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.

View File

@ -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 This file summarizes known NuttX bugs, limitations, inconsistencies with
@ -16,7 +16,7 @@ nuttx/
(17) Network (net/, drivers/net) (17) Network (net/, drivers/net)
(3) USB (drivers/usbdev, drivers/usbhost) (3) USB (drivers/usbdev, drivers/usbhost)
(11) Libraries (lib/) (11) Libraries (lib/)
(10) File system/Generic drivers (fs/, drivers/) (9) File system/Generic drivers (fs/, drivers/)
(5) Graphics subystem (graphics/) (5) Graphics subystem (graphics/)
(1) Pascal add-on (pcode/) (1) Pascal add-on (pcode/)
(1) Documentation (Documentation/) (1) Documentation (Documentation/)
@ -750,21 +750,6 @@ o File system / Generic drivers (fs/, drivers/)
Status: Open Status: Open
Priority: Low 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 Title: POLLHUP SUPPORT
Description: All drivers that support the poll method should also report Description: All drivers that support the poll method should also report
POLLHUP event when the driver is closedd. POLLHUP event when the driver is closedd.

View File

@ -112,16 +112,29 @@ static const struct file_operations g_serialops =
* Name: uart_takesem * 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 only case that an error should occur here is if the wait was awakened
* the wait was awakened by a signal. * by a signal.
*/ */
ASSERT(get_errno() == EINTR); 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 * 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; irqstate_t flags;
int nexthead; int nexthead;
int ret;
/* Increment to see what the next head pointer will be. We need to use the "next" /* 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 * 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.buffer[dev->xmit.head] = ch;
dev->xmit.head = nexthead; dev->xmit.head = nexthead;
return; return OK;
} }
else else
{ {
/* Inform the interrupt level logic that we are waiting. /* Inform the interrupt level logic that we are waiting. This and
* This and the following steps must be atomic. * the following steps must be atomic.
*/ */
flags = irqsave(); flags = irqsave();
dev->xmitwaiting = true; dev->xmitwaiting = true;
/* Wait for some characters to be sent from the buffer /* Wait for some characters to be sent from the buffer with the TX
* with the TX interrupt enabled. When the TX interrupt * interrupt enabled. When the TX interrupt is enabled, uart_xmitchars
* is enabled, uart_xmitchars should execute and remove * should execute and remove some of the data from the TX buffer.
* some of the data from the TX buffer.
*/ */
uart_enabletxint(dev); uart_enabletxint(dev);
uart_takesem(&dev->xmitsem); ret = uart_takesem(&dev->xmitsem, true);
uart_disabletxint(dev); uart_disabletxint(dev);
irqrestore(flags); 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) static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t buflen)
{ {
FAR struct inode *inode = filep->f_inode; FAR struct inode *inode = filep->f_inode;
FAR uart_dev_t *dev = inode->i_private; FAR uart_dev_t *dev = inode->i_private;
ssize_t ret = buflen; ssize_t nread = buflen;
int ret;
/* We may receive console writes through this path from /* We may receive console writes through this path from
* interrupt handlers and from debug output in the IDLE task! * 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. /* 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 * 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++; int ch = *buffer++;
/* Put the character into the transmit buffer */ /* If this is the console, then we should replace LF with CR-LF */
uart_putxmitchar(dev, ch);
/* If this is the console, then we should replace LF with LF-CR */
ret = OK;
if (dev->isconsole && ch == '\n') if (dev->isconsole && ch == '\n')
{ {
uart_putxmitchar(dev, '\r'); ret = uart_putxmitchar(dev, '\r');
}
/* Put the character into the transmit buffer */
if (ret == OK)
{
ret = uart_putxmitchar(dev, ch);
}
/* Were we awakened by a signal? That should be the only condition that
* uart_putxmitchar() should return an error.
*/
if (ret < 0)
{
/* 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); 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; irqstate_t flags;
ssize_t recvd = 0; ssize_t recvd = 0;
int16_t tail; 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. /* 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 * 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; tail = 0;
} }
dev->recv.tail = tail; 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); uart_enablerxint(dev);
/* Now wait with the Rx interrupt re-enabled. NuttX will /* Now wait with the Rx interrupt re-enabled. NuttX will
* automatically re-enable global interrupts when this * automatically re-enable global interrupts when this thread
* thread goes to sleep. * goes to sleep.
*/ */
uart_takesem(&dev->recvsem); ret = uart_takesem(&dev->recvsem, true);
irqrestore(flags); 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 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; FAR uart_dev_t *dev = inode->i_private;
pollevent_t eventset; pollevent_t eventset;
int ndx; int ndx;
int ret = OK; int ret;
int i; int i;
/* Some sanity checking */ /* 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? */ /* 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) if (setup)
{ {
/* This is a request to set up the poll. Find an available /* 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; 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. * 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; eventset = 0;
(void)uart_takesem(&dev->xmit.sem, false);
uart_takesem(&dev->xmit.sem);
ndx = dev->xmit.head + 1; ndx = dev->xmit.head + 1;
if (ndx >= dev->xmit.size) if (ndx >= dev->xmit.size)
{ {
ndx = 0; ndx = 0;
} }
if (ndx != dev->xmit.tail) if (ndx != dev->xmit.tail)
{ {
eventset |= POLLOUT; eventset |= POLLOUT;
} }
uart_givesem(&dev->xmit.sem); 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) if (dev->recv.head != dev->recv.tail)
{ {
eventset |= POLLIN; eventset |= POLLIN;
} }
uart_givesem(&dev->recv.sem); uart_givesem(&dev->recv.sem);
if (eventset) if (eventset)
@ -588,7 +715,13 @@ static int uart_close(FAR struct file *filep)
FAR uart_dev_t *dev = inode->i_private; FAR uart_dev_t *dev = inode->i_private;
irqstate_t flags; 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) if (dev->open_count > 1)
{ {
dev->open_count--; dev->open_count--;
@ -653,11 +786,19 @@ static int uart_open(FAR struct file *filep)
struct inode *inode = filep->f_inode; struct inode *inode = filep->f_inode;
uart_dev_t *dev = inode->i_private; uart_dev_t *dev = inode->i_private;
uint8_t tmp; 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.
*/
uart_takesem(&dev->closesem); ret = uart_takesem(&dev->closesem, true);
if (ret < 0)
{
/* A signal received while waiting for the last close operation. */
return ret;
}
/* Start up serial port */ /* Start up serial port */
/* Increment the count of references to the device. */ /* Increment the count of references to the device. */

View File

@ -58,14 +58,17 @@
#define SIOCDARP _ARPIOC(2) /* Delete an ARP mapping */ #define SIOCDARP _ARPIOC(2) /* Delete an ARP mapping */
#define SIOCGARP _ARPIOC(3) /* Get an ARP mapping */ #define SIOCGARP _ARPIOC(3) /* Get an ARP mapping */
/* Values for the FLAGS field in struct arpreq */ /* 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 0x01 /* Lookup complete */ #define ATF_COM (1 << 0) /* Lookup complete */
#define ATF_PERM 0x02 /* Permanent entry */ #define ATF_PERM (1 << 1) /* Permanent entry */
#define ATF_PUBL 0x04 /* Publish entry */ #define ATF_PUBL (1 << 2) /* Publish entry */
#define ATF_USETRAILERS 0x10 /* Trailers requested */ #define ATF_USETRAILERS (1 << 3) /* Trailers requested (obsolete) */
#define ATF_NETMASK 0x20 /* Use a netmask */ #define ATF_NETMASK (1 << 4) /* Use a netmask */
#define ATF_DONTPUB 0x40 /* Don't answer */ #define ATF_DONTPUB (1 << 5) /* Don't answer */
/**************************************************************************** /****************************************************************************
* Public Type Definitions * Public Type Definitions

View File

@ -149,6 +149,7 @@
/**************************************************************************** /****************************************************************************
* Type Definitions * Type Definitions
****************************************************************************/ ****************************************************************************/
/* See include/net/if.h */
/**************************************************************************** /****************************************************************************
* Public Function Prototypes * Public Function Prototypes

View File

@ -2,7 +2,7 @@
* lib/stdio/lib_libfwrite.c * lib/stdio/lib_libfwrite.c
* *
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. * 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* lib/stdio/lib_lowinstream.c * lib/stdio/lib_lowinstream.c
* *
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011-2012 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -42,7 +42,9 @@
#ifdef CONFIG_ARCH_LOWGETC #ifdef CONFIG_ARCH_LOWGETC
#include <stdio.h> #include <stdio.h>
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include "lib_internal.h" #include "lib_internal.h"
@ -57,10 +59,19 @@
static int lowinstream_getc(FAR struct lib_instream_s *this) 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++; this->nget++;
} }
return ret;
} }
/**************************************************************************** /****************************************************************************

View File

@ -42,6 +42,7 @@
#ifdef CONFIG_ARCH_LOWPUTC #ifdef CONFIG_ARCH_LOWPUTC
#include <stdio.h> #include <stdio.h>
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
@ -57,7 +58,9 @@
static void lowoutstream_putc(FAR struct lib_outstream_s *this, int ch) 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++; this->nput++;
} }

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* lib/stdio/lib_meminstream.c * lib/stdio/lib_meminstream.c
* *
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011-2012 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -37,6 +37,8 @@
* Included Files * Included Files
****************************************************************************/ ****************************************************************************/
#include <assert.h>
#include "lib_internal.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; FAR struct lib_meminstream_s *mthis = (FAR struct lib_meminstream_s *)this;
int ret; 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]; ret = mthis->buffer[this->nget];
this->nget++; this->nget++;
@ -61,6 +67,7 @@ static int meminstream_getc(FAR struct lib_instream_s *this)
{ {
ret = EOF; ret = EOF;
} }
return ret; return ret;
} }

View File

@ -37,6 +37,8 @@
* Included Files * Included Files
****************************************************************************/ ****************************************************************************/
#include <assert.h>
#include "lib_internal.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; 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 /* If this will not overrun the buffer, then write the character to the
* buffer. Not that buflen was pre-decremented when the stream was * 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. * 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; mthis->buffer[this->nput] = ch;
this->nput++; this->nput++;

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* lib/stdio/lib_nullinstream.c * lib/stdio/lib_nullinstream.c
* *
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011-2012 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -39,6 +39,7 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include "lib_internal.h" #include "lib_internal.h"
/**************************************************************************** /****************************************************************************

View File

@ -38,7 +38,9 @@
****************************************************************************/ ****************************************************************************/
#include <stdio.h> #include <stdio.h>
#include <assert.h>
#include <errno.h> #include <errno.h>
#include "lib_internal.h" #include "lib_internal.h"
/**************************************************************************** /****************************************************************************
@ -47,6 +49,7 @@
static void nulloutstream_putc(FAR struct lib_outstream_s *this, int ch) static void nulloutstream_putc(FAR struct lib_outstream_s *this, int ch)
{ {
DEBUGASSERT(this);
this->nput++; this->nput++;
} }

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* lib/stdio/lib_rawinstream.c * lib/stdio/lib_rawinstream.c
* *
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011-2012 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -38,7 +38,9 @@
****************************************************************************/ ****************************************************************************/
#include <unistd.h> #include <unistd.h>
#include <assert.h>
#include <errno.h> #include <errno.h>
#include "lib_internal.h" #include "lib_internal.h"
/**************************************************************************** /****************************************************************************
@ -52,23 +54,27 @@
static int rawinstream_getc(FAR struct lib_instream_s *this) static int rawinstream_getc(FAR struct lib_instream_s *this)
{ {
FAR struct lib_rawinstream_s *rthis = (FAR struct lib_rawinstream_s *)this; FAR struct lib_rawinstream_s *rthis = (FAR struct lib_rawinstream_s *)this;
int nwritten;
char ch; 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; this->nget++;
do return ch;
{
nwritten = read(rthis->fd, &ch, 1);
if (nwritten == 1)
{
this->nget++;
return ch;
}
}
while (nwritten < 0 && get_errno() == EINTR);
} }
/* 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; return EOF;
} }

View File

@ -38,7 +38,9 @@
****************************************************************************/ ****************************************************************************/
#include <unistd.h> #include <unistd.h>
#include <assert.h>
#include <errno.h> #include <errno.h>
#include "lib_internal.h" #include "lib_internal.h"
/**************************************************************************** /****************************************************************************
@ -52,19 +54,28 @@
static void rawoutstream_putc(FAR struct lib_outstream_s *this, int ch) static void rawoutstream_putc(FAR struct lib_outstream_s *this, int ch)
{ {
FAR struct lib_rawoutstream_s *rthis = (FAR struct lib_rawoutstream_s *)this; FAR struct lib_rawoutstream_s *rthis = (FAR struct lib_rawoutstream_s *)this;
int nwritten;
char buffer = ch; char buffer = ch;
if (this && rthis->fd >= 0)
DEBUGASSERT(this && rthis->fd >= 0);
/* Loop until the character is successfully transferred */
for (;;)
{ {
int nwritten; nwritten = write(rthis->fd, &buffer, 1);
do if (nwritten == 1)
{ {
nwritten = write(rthis->fd, &buffer, 1); this->nput++;
if (nwritten == 1) return;
{
this->nput++;
}
} }
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);
} }
} }

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* lib/stdio/lib_stdinstream.c * lib/stdio/lib_stdinstream.c
* *
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011-2012 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -37,6 +37,8 @@
* Included Files * Included Files
****************************************************************************/ ****************************************************************************/
#include <assert.h>
#include "lib_internal.h" #include "lib_internal.h"
/**************************************************************************** /****************************************************************************
@ -50,16 +52,19 @@
static int stdinstream_getc(FAR struct lib_instream_s *this) static int stdinstream_getc(FAR struct lib_instream_s *this)
{ {
FAR struct lib_stdinstream_s *sthis = (FAR struct lib_stdinstream_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); this->nget++;
if (ret != EOF)
{
this->nget++;
}
return ret;
} }
return EOF;
return ret;
} }
/**************************************************************************** /****************************************************************************

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* lib/stdio/lib_stdoutstream.c * lib/stdio/lib_stdoutstream.c
* *
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011-2012 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -38,6 +38,8 @@
****************************************************************************/ ****************************************************************************/
#include <fcntl.h> #include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include "lib_internal.h" #include "lib_internal.h"
@ -52,12 +54,26 @@
static void stdoutstream_putc(FAR struct lib_outstream_s *this, int ch) static void stdoutstream_putc(FAR struct lib_outstream_s *this, int ch)
{ {
FAR struct lib_stdoutstream_s *sthis = (FAR struct lib_stdoutstream_s *)this; 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++; this->nput++;
return;
} }
/* EINTR (meaning that fputc was interrupted by a signal) is the only
* expected error.
*/
DEBUGASSERT(get_errno() == EINTR);
} }
} }

View File

@ -40,6 +40,7 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <nuttx/syslog.h> #include <nuttx/syslog.h>
@ -62,10 +63,31 @@
static void syslogstream_putc(FAR struct lib_outstream_s *this, int ch) static void syslogstream_putc(FAR struct lib_outstream_s *this, int ch)
{ {
/* Write the character to the supported logging device */ int ret;
(void)syslog_putc(ch); /* Try writing until the write was successful or until an irrecoverable
this->nput++; * 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);
}
} }
/**************************************************************************** /****************************************************************************