This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 573115734d Revert "drivers/pipes: return after short write if buffer 
is full"
573115734d is described below

commit 573115734debdfbd27453fdf4206ff92b878a055
Author: Xiang Xiao <[email protected]>
AuthorDate: Tue Nov 26 17:08:49 2024 +0800

    Revert "drivers/pipes: return after short write if buffer is full"
    
    This reverts commit d0680fd1bc51b7ead0b068fb24a31a144d22dc6c.
---
 drivers/pipes/pipe_common.c | 127 +++++++++++++++++++++++++++++---------------
 1 file changed, 84 insertions(+), 43 deletions(-)

diff --git a/drivers/pipes/pipe_common.c b/drivers/pipes/pipe_common.c
index f9b944c459..594c1c198b 100644
--- a/drivers/pipes/pipe_common.c
+++ b/drivers/pipes/pipe_common.c
@@ -506,6 +506,7 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const 
char *buffer,
   FAR struct inode      *inode    = filep->f_inode;
   FAR struct pipe_dev_s *dev      = inode->i_private;
   ssize_t                nwritten = 0;
+  ssize_t                last;
   int                    ret;
 
   DEBUGASSERT(dev);
@@ -545,70 +546,110 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR 
const char *buffer,
       return ret;
     }
 
-  /* REVISIT:  "If all file descriptors referring to the read end of a
-   * pipe have been closed, then a write will cause a SIGPIPE signal to
-   * be generated for the calling process.  If the calling process is
-   * ignoring this signal, then write(2) fails with the error EPIPE."
-   */
+  /* Loop until all of the bytes have been written */
 
-  if (dev->d_nreaders <= 0 && PIPE_IS_POLICY_0(dev->d_flags))
+  last = 0;
+  for (; ; )
     {
-      nxrmutex_unlock(&dev->d_bflock);
-      return -EPIPE;
-    }
-
-  /* Would the next write overflow the circular buffer? */
+      /* REVISIT:  "If all file descriptors referring to the read end of a
+       * pipe have been closed, then a write will cause a SIGPIPE signal to
+       * be generated for the calling process.  If the calling process is
+       * ignoring this signal, then write(2) fails with the error EPIPE."
+       */
 
-  while (circbuf_is_full(&dev->d_buffer))
-    {
-      if (filep->f_oflags & O_NONBLOCK)
+      if (dev->d_nreaders <= 0 && PIPE_IS_POLICY_0(dev->d_flags))
         {
-          /* If O_NONBLOCK was set, then return EGAIN. */
-
           nxrmutex_unlock(&dev->d_bflock);
-          return -EAGAIN;
+          return nwritten == 0 ? -EPIPE : nwritten;
         }
-      else
+
+      /* Would the next write overflow the circular buffer? */
+
+      if (!circbuf_is_full(&dev->d_buffer))
         {
-          /* Wait for data to be removed from the pipe. */
+          /* Loop until all of the bytes have been written */
 
-          nxrmutex_unlock(&dev->d_bflock);
-          ret = nxsem_wait(&dev->d_wrsem);
-          if (ret < 0 || (ret = nxrmutex_lock(&dev->d_bflock)) < 0)
+          nwritten += circbuf_write(&dev->d_buffer,
+                                    buffer + nwritten, len - nwritten);
+
+          if ((size_t)nwritten == len)
             {
-              /* Either call nxsem_wait may fail because a signal was
-               * received or if the task was canceled.
+              /* Notify all poll/select waiters that they can read from the
+               * FIFO when buffer used exceeds poll threshold.
                */
 
-              return (ssize_t)ret;
+              if (circbuf_used(&dev->d_buffer) > dev->d_pollinthrd)
+                {
+                  poll_notify(dev->d_fds, CONFIG_DEV_PIPE_NPOLLWAITERS,
+                              POLLIN);
+                }
+
+              /* Yes.. Notify all of the waiting readers that more data is
+               * available.
+               */
+
+              pipecommon_wakeup(&dev->d_rdsem);
+
+              /* Return the number of bytes written */
+
+              nxrmutex_unlock(&dev->d_bflock);
+              return len;
             }
         }
-    }
+      else
+        {
+          /* There is not enough room for the next byte.  Was anything
+           * written in this pass?
+           */
 
-  /* Write data to buffer. */
+          if (last < nwritten)
+            {
+              /* Notify all poll/select waiters that they can read from the
+               * FIFO.
+               */
 
-  nwritten = circbuf_write(&dev->d_buffer, buffer, len);
+              poll_notify(dev->d_fds, CONFIG_DEV_PIPE_NPOLLWAITERS, POLLIN);
 
-  /* Notify all poll/select waiters that they can read from the
-   * FIFO when buffer used exceeds poll threshold.
-   */
+              /* Yes.. Notify all of the waiting readers that more data is
+               * available.
+               */
 
-  if (circbuf_used(&dev->d_buffer) > dev->d_pollinthrd)
-    {
-      poll_notify(dev->d_fds, CONFIG_DEV_PIPE_NPOLLWAITERS,
-                  POLLIN);
-    }
+              pipecommon_wakeup(&dev->d_rdsem);
+            }
 
-  /* Yes.. Notify all of the waiting readers that more data is
-   * available.
-   */
+          last = nwritten;
 
-  pipecommon_wakeup(&dev->d_rdsem);
+          /* If O_NONBLOCK was set, then return partial bytes written or
+           * EGAIN.
+           */
 
-  /* Return the number of bytes written */
+          if (filep->f_oflags & O_NONBLOCK)
+            {
+              if (nwritten == 0)
+                {
+                  nwritten = -EAGAIN;
+                }
 
-  nxrmutex_unlock(&dev->d_bflock);
-  return nwritten;
+              nxrmutex_unlock(&dev->d_bflock);
+              return nwritten;
+            }
+
+          /* There is more to be written.. wait for data to be removed from
+           * the pipe
+           */
+
+          nxrmutex_unlock(&dev->d_bflock);
+          ret = nxsem_wait(&dev->d_wrsem);
+          if (ret < 0 || (ret = nxrmutex_lock(&dev->d_bflock)) < 0)
+            {
+              /* Either call nxsem_wait may fail because a signal was
+               * received or if the task was canceled.
+               */
+
+              return nwritten == 0 ? (ssize_t)ret : nwritten;
+            }
+        }
+    }
 }
 
 /****************************************************************************

Reply via email to