Commit 5792d7d3 authored by Chrysostomos Nanakos's avatar Chrysostomos Nanakos

xseg_posixfd: Refactor FIFO creation & pipe ops

* Remove retry loop in FIFO creation. If FIFO already exist's
  do not unlink and re-create the named pipe. Also note that
  mkfifo() is thread-safe and async-cancel-safe.

* As it happens with pipes, writing to a FIFO with no connected
  readers will fail with EPIPE and also deliver a SIGPIPE signal
  to the writer. Reading from a FIFO with no connected writers will
  return an EOF to the reader. Setting the O_RDWR flag while opening
  the pipe will create an equal number of connected readers/writers
  to the kernel and will ensure that both are above zero.
  This implementation will NEVER block since the process can at least
  talk to itself.
  ** POSIX.1 leaves this case "undefined" when O_NONBLOCK is set. **

* Drain the pipe even if the call was interrupted by a signal
  before any data was read. Optimize drain loop to make the
  minimum number of read syscall's.

* Write to the pipe even if the call was interrupted by a signal
  before any data was written.
parent b3711969
......@@ -33,7 +33,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <xseg/xseg.h>
#include <xseg/xobj.h>
#include <xseg_posixfd.h>
#define ERRSIZE 512
#define FIFO_RDWR_UGO S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
char errbuf[ERRSIZE];
static struct posixfd_signal_desc * __get_signal_desc(struct xseg *xseg, xport portno)
......@@ -76,24 +78,17 @@ static int posixfd_local_signal_init(struct xseg *xseg, xport portno)
}
__get_filename(psd, filename);
retry:
r = mkfifo(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
if (r < 0) {
if (errno == EEXIST) {
unlink(filename);
goto retry;
}
if (mkfifo(filename, FIFO_RDWR_UGO) < 0 && errno != EEXIST) {
return -1;
}
fd = open(filename, O_RDONLY | O_NONBLOCK);
if (fd < 0) {
/* Ensure that the count of connected readers/writers is above zero */
if ((fd = open(filename, O_RDWR | O_NONBLOCK)) < 0) {
unlink(filename);
return -1;
}
psd->fd = fd;
open(filename, O_WRONLY | O_NONBLOCK);
return 0;
}
......@@ -107,10 +102,12 @@ static void posixfd_local_signal_quit(struct xseg *xseg, xport portno)
{
char filename[POSIXFD_DIR_LEN + POSIXFD_FILENAME_LEN + 1];
struct posixfd_signal_desc *psd = __get_signal_desc(xseg, portno);
if (psd->fd >=0) {
close(psd->fd);
psd->fd = -1;
}
__get_filename(psd, filename);
unlink(filename);
return;
......@@ -154,27 +151,43 @@ static void posixfd_remote_signal_quit(void)
static int posixfd_prepare_wait(struct xseg *xseg, uint32_t portno)
{
char buf[512];
int buf_size = 512;
size_t len;
int value = 0;
struct posixfd_signal_desc *psd = __get_signal_desc(xseg, portno);
if (!psd)
if (!psd) {
return -1;
}
psd->flag = 1;
while (read(psd->fd, buf, buf_size) > 0);
return 0;
/* Drain the pipe */
do {
len = read(psd->fd, buf, sizeof(buf));
value |= (len > 0 ? 0 : -1);
} while ((len == -1 && errno == EINTR) || len == sizeof(buf));
return value;
}
static int posixfd_cancel_wait(struct xseg *xseg, uint32_t portno)
{
char buf[512];
int buf_size = 512;
size_t len;
int value = 0;
struct posixfd_signal_desc *psd = __get_signal_desc(xseg, portno);
if (!psd)
if (!psd) {
return -1;
}
psd->flag = 0;
while (read(psd->fd, buf, buf_size) > 0);
return 0;
/* Drain the pipe */
do {
len = read(psd->fd, buf, sizeof(buf));
value |= (len > 0 ? 0 : -1);
} while ((len == -1 && errno == EINTR) || len == sizeof(buf));
return value;
}
/*
......@@ -190,12 +203,14 @@ static int posixfd_wait_signal(struct xseg *xseg, void *sd, uint32_t usec_timeou
int r;
struct timeval tv;
char buf[512];
int buf_size = 512;
size_t len;
int value = 0;
fd_set fds;
struct posixfd_signal_desc *psd = (struct posixfd_signal_desc *)sd;
if (!psd)
if (!psd) {
return -1;
}
tv.tv_sec = usec_timeout / 1000000;
tv.tv_usec = usec_timeout - tv.tv_sec * 1000000;
......@@ -215,11 +230,14 @@ static int posixfd_wait_signal(struct xseg *xseg, void *sd, uint32_t usec_timeou
}
if (r != 0) {
/* clean up pipe */
while (read(psd->fd, buf, buf_size) > 0);
/* Drain the pipe */
do {
len = read(psd->fd, buf, sizeof(buf));
value |= (len > 0 ? 0 : -1);
} while ((len == -1 && errno == EINTR) || len == sizeof(buf));
}
return 0;
return value;
}
/*
......@@ -251,7 +269,11 @@ static int posixfd_signal(struct xseg *xseg, uint32_t portno)
if (fd < 0) {
return -1;
}
r = write(fd, "a", 1);
do {
r = write(fd, "a", 1);
} while (r < 0 && errno == EINTR);
if (r < 0) {
close(fd);
return -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment