diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-03-02 00:33:42 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-03-02 00:33:42 +0000 |
commit | 9d5aa7cbb885563b3e1d8405ffc4663eaaf51dc7 (patch) | |
tree | a89768fa9a4aac8ecc614d06feb525ec35dcc1c2 /nuttx/drivers/pipes | |
parent | b9fd3d2acfda5074d62e671c6edcdaed9fdc40c9 (diff) | |
download | px4-nuttx-9d5aa7cbb885563b3e1d8405ffc4663eaaf51dc7.tar.gz px4-nuttx-9d5aa7cbb885563b3e1d8405ffc4663eaaf51dc7.tar.bz2 px4-nuttx-9d5aa7cbb885563b3e1d8405ffc4663eaaf51dc7.zip |
Fix pipe/fifo open logic: semaphore wait in open() must abort if a signal is received
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3327 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/drivers/pipes')
-rw-r--r-- | nuttx/drivers/pipes/pipe_common.c | 104 |
1 files changed, 63 insertions, 41 deletions
diff --git a/nuttx/drivers/pipes/pipe_common.c b/nuttx/drivers/pipes/pipe_common.c index e22678688..a6af41fe1 100644 --- a/nuttx/drivers/pipes/pipe_common.c +++ b/nuttx/drivers/pipes/pipe_common.c @@ -1,7 +1,7 @@ /**************************************************************************** * drivers/pipes/pipe_common.c * - * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -184,6 +184,7 @@ int pipecommon_open(FAR struct file *filep) struct inode *inode = filep->f_inode; struct pipe_dev_s *dev = inode->i_private; int sval; + int ret; /* Some sanity checking */ #if CONFIG_DEBUG @@ -192,66 +193,87 @@ int pipecommon_open(FAR struct file *filep) return -EBADF; } #endif - /* Make sure that we have exclusive access to the device structure */ + /* Make sure that we have exclusive access to the device structure. The + * sem_wait() call should fail only if we are awakened by a signal. + */ - if (sem_wait(&dev->d_bfsem) == 0) + ret = sem_wait(&dev->d_bfsem); + if (ret != OK) { - /* If this the first reference on the device, then allocate the buffer */ + fdbg("sem_wait failed: %d\n", errno); + DEBUGASSERT(errno > 0); + return -errno; + } - if (dev->d_refs == 0) + /* If this the first reference on the device, then allocate the buffer */ + + if (dev->d_refs == 0) + { + dev->d_buffer = (uint8_t*)malloc(CONFIG_DEV_PIPE_SIZE); + if (!dev->d_buffer) { - dev->d_buffer = (uint8_t*)malloc(CONFIG_DEV_PIPE_SIZE); - if (!dev->d_buffer) - { - (void)sem_post(&dev->d_bfsem); - return -ENOMEM; - } + (void)sem_post(&dev->d_bfsem); + return -ENOMEM; } + } - /* Increment the reference count on the pipe instance */ + /* Increment the reference count on the pipe instance */ - dev->d_refs++; + dev->d_refs++; - /* If opened for writing, increment the count of writers on on the pipe instance */ + /* If opened for writing, increment the count of writers on on the pipe instance */ - if ((filep->f_oflags & O_WROK) != 0) - { - dev->d_nwriters++; + if ((filep->f_oflags & O_WROK) != 0) + { + dev->d_nwriters++; - /* If this this is the first writer, then the read semaphore indicates the - * number of readers waiting for the first writer. Wake them all up. - */ + /* If this this is the first writer, then the read semaphore indicates the + * number of readers waiting for the first writer. Wake them all up. + */ - if (dev->d_nwriters == 1) + if (dev->d_nwriters == 1) + { + while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval < 0) { - while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval < 0) - { - sem_post(&dev->d_rdsem); - } + sem_post(&dev->d_rdsem); } } + } - /* If opened for read-only, then wait for at least one writer on the pipe */ + /* If opened for read-only, then wait for at least one writer on the pipe */ - sched_lock(); - (void)sem_post(&dev->d_bfsem); - if ((filep->f_oflags & O_RDWR) == O_RDONLY && dev->d_nwriters < 1) + sched_lock(); + (void)sem_post(&dev->d_bfsem); + if ((filep->f_oflags & O_RDWR) == O_RDONLY && dev->d_nwriters < 1) + { + /* NOTE: d_rdsem is normally used when the read logic waits for more + * data to be written. But until the first writer has opened the + * pipe, the meaning is different: it is used prevent O_RDONLY open + * calls from returning until there is at least one writer on the pipe. + * This is required both by spec and also because it prevents + * subsequent read() calls from returning end-of-file because there is + * no writer on the pipe. + */ + + ret = sem_wait(&dev->d_rdsem); + if (ret != OK) { - /* NOTE: d_rdsem is normally used when the read logic waits for more - * data to be written. But until the first writer has opened the - * pipe, the meaning is different: it is used prevent O_RDONLY open - * calls from returning until there is at least one writer on the pipe. - * This is required both by spec and also because it prevents - * subsequent read() calls from returning end-of-file because there is - * no writer on the pipe. + /* The sem_wait() call should fail only if we are awakened by + * a signal. */ - pipecommon_semtake(&dev->d_rdsem); + fdbg("sem_wait failed: %d\n", errno); + DEBUGASSERT(errno > 0); + ret = -errno; + + /* Immediately close the pipe that we just opened */ + + (void)pipecommon_close(filep); } - sched_unlock(); - return OK; - } - return ERROR; + } + + sched_unlock(); + return ret; } /**************************************************************************** |