|
@@ -40,10 +40,6 @@ typedef __kernel_pid_t pid_t;
|
|
|
#include <linux/un.h>
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
-#ifndef FIONREAD
|
|
|
-#define FIONREAD 0x541B
|
|
|
-#endif
|
|
|
-
|
|
|
static int pipe_path(int pipeid, char* path, int len) {
|
|
|
/* use abstract UNIX sockets for pipes */
|
|
|
memset(path, 0, len);
|
|
@@ -122,7 +118,7 @@ static int pipe_waitforclient(PAL_HANDLE handle, PAL_HANDLE* client) {
|
|
|
|
|
|
PAL_HANDLE clnt = malloc(HANDLE_SIZE(pipe));
|
|
|
SET_HANDLE_TYPE(clnt, pipecli);
|
|
|
- HANDLE_HDR(clnt)->flags |= RFD(0) | WFD(0) | WRITABLE(0);
|
|
|
+ HANDLE_HDR(clnt)->flags |= RFD(0) | WFD(0);
|
|
|
clnt->pipe.fd = newfd;
|
|
|
clnt->pipe.pipeid = handle->pipe.pipeid;
|
|
|
clnt->pipe.nonblocking = PAL_FALSE;
|
|
@@ -160,7 +156,7 @@ static int pipe_connect(PAL_HANDLE* handle, PAL_NUM pipeid, int options) {
|
|
|
|
|
|
PAL_HANDLE hdl = malloc(HANDLE_SIZE(pipe));
|
|
|
SET_HANDLE_TYPE(hdl, pipe);
|
|
|
- HANDLE_HDR(hdl)->flags |= RFD(0) | WFD(0) | WRITABLE(0);
|
|
|
+ HANDLE_HDR(hdl)->flags |= RFD(0) | WFD(0);
|
|
|
hdl->pipe.fd = fd;
|
|
|
hdl->pipe.pipeid = pipeid;
|
|
|
hdl->pipe.nonblocking = (options & PAL_OPTION_NONBLOCK) ? PAL_TRUE : PAL_FALSE;
|
|
@@ -178,7 +174,7 @@ static int pipe_private(PAL_HANDLE* handle, int options) {
|
|
|
|
|
|
PAL_HANDLE hdl = malloc(HANDLE_SIZE(pipeprv));
|
|
|
SET_HANDLE_TYPE(hdl, pipeprv);
|
|
|
- HANDLE_HDR(hdl)->flags |= RFD(0) | WFD(1) | WRITABLE(1);
|
|
|
+ HANDLE_HDR(hdl)->flags |= RFD(0) | WFD(1);
|
|
|
hdl->pipeprv.fds[0] = fds[0];
|
|
|
hdl->pipeprv.fds[1] = fds[1];
|
|
|
hdl->pipeprv.nonblocking = (options & PAL_OPTION_NONBLOCK) ? PAL_TRUE : PAL_FALSE;
|
|
@@ -250,14 +246,6 @@ static int64_t pipe_write(PAL_HANDLE handle, uint64_t offset, size_t len, const
|
|
|
int64_t bytes = 0;
|
|
|
|
|
|
bytes = INLINE_SYSCALL(write, 3, fd, buffer, len);
|
|
|
-
|
|
|
- PAL_FLG writable = IS_HANDLE_TYPE(handle, pipeprv) ? WRITABLE(1) : WRITABLE(0);
|
|
|
-
|
|
|
- if (!IS_ERR(bytes) && (size_t)bytes == len)
|
|
|
- HANDLE_HDR(handle)->flags |= writable;
|
|
|
- else
|
|
|
- HANDLE_HDR(handle)->flags &= ~writable;
|
|
|
-
|
|
|
if (IS_ERR(bytes))
|
|
|
bytes = unix_to_pal_error(ERRNO(bytes));
|
|
|
|
|
@@ -344,35 +332,53 @@ static int pipe_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
|
|
|
int ret;
|
|
|
int val;
|
|
|
|
|
|
- if (handle->generic.fds[0] == PAL_IDX_POISON)
|
|
|
+ if (handle->pipe.fd == PAL_IDX_POISON)
|
|
|
return -PAL_ERROR_BADHANDLE;
|
|
|
|
|
|
attr->handle_type = HANDLE_HDR(handle)->type;
|
|
|
attr->nonblocking = IS_HANDLE_TYPE(handle, pipeprv) ? handle->pipeprv.nonblocking
|
|
|
: handle->pipe.nonblocking;
|
|
|
attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
|
|
|
- attr->writable = PAL_FALSE;
|
|
|
|
|
|
/* get number of bytes available for reading (doesn't make sense for "listening" pipes) */
|
|
|
attr->pending_size = 0;
|
|
|
if (!IS_HANDLE_TYPE(handle, pipesrv)) {
|
|
|
- ret = INLINE_SYSCALL(ioctl, 3, handle->generic.fds[0], FIONREAD, &val);
|
|
|
+ ret = INLINE_SYSCALL(ioctl, 3, handle->pipe.fd, FIONREAD, &val);
|
|
|
if (IS_ERR(ret))
|
|
|
return unix_to_pal_error(ERRNO(ret));
|
|
|
|
|
|
attr->pending_size = val;
|
|
|
- attr->writable = HANDLE_HDR(handle)->flags & (IS_HANDLE_TYPE(handle, pipeprv)
|
|
|
- ? WRITABLE(1) : WRITABLE(0));
|
|
|
}
|
|
|
|
|
|
- /* query if there is data available for reading */
|
|
|
- struct pollfd pfd = {.fd = handle->generic.fds[0], .events = POLLIN, .revents = 0};
|
|
|
- struct timespec tp = {0, 0};
|
|
|
- ret = INLINE_SYSCALL(ppoll, 5, &pfd, 1, &tp, NULL, 0);
|
|
|
- if (IS_ERR(ret))
|
|
|
- return unix_to_pal_error(ERRNO(ret));
|
|
|
+ /* query if there is data available for reading/writing */
|
|
|
+ if (IS_HANDLE_TYPE(handle, pipeprv)) {
|
|
|
+ /* for private pipe, readable and writable are queried on different fds */
|
|
|
+ struct pollfd pfd[2] = {{.fd = handle->pipeprv.fds[0], .events = POLLIN, .revents = 0},
|
|
|
+ {.fd = handle->pipeprv.fds[1], .events = POLLOUT, .revents = 0}};
|
|
|
+ struct timespec tp = {0, 0};
|
|
|
+ ret = INLINE_SYSCALL(ppoll, 5, &pfd, 2, &tp, NULL, 0);
|
|
|
+ if (IS_ERR(ret))
|
|
|
+ return unix_to_pal_error(ERRNO(ret));
|
|
|
+
|
|
|
+ attr->readable = ret >= 1 && (pfd[0].revents & (POLLIN | POLLERR | POLLHUP)) == POLLIN;
|
|
|
+ attr->writable = ret >= 1 && (pfd[1].revents & (POLLOUT | POLLERR | POLLHUP)) == POLLOUT;
|
|
|
+ } else {
|
|
|
+ /* for non-private pipes, both readable and writable are queried on the same fd */
|
|
|
+ short pfd_events = POLLIN;
|
|
|
+ if (!IS_HANDLE_TYPE(handle, pipesrv)) {
|
|
|
+ /* querying for writing doesn't make sense for "listening" pipes */
|
|
|
+ pfd_events |= POLLOUT;
|
|
|
+ }
|
|
|
|
|
|
- attr->readable = (ret == 1 && pfd.revents == POLLIN);
|
|
|
+ struct pollfd pfd = {.fd = handle->pipe.fd, .events = pfd_events, .revents = 0};
|
|
|
+ struct timespec tp = {0, 0};
|
|
|
+ ret = INLINE_SYSCALL(ppoll, 5, &pfd, 1, &tp, NULL, 0);
|
|
|
+ if (IS_ERR(ret))
|
|
|
+ return unix_to_pal_error(ERRNO(ret));
|
|
|
+
|
|
|
+ attr->readable = ret == 1 && (pfd.revents & (POLLIN | POLLERR | POLLHUP)) == POLLIN;
|
|
|
+ attr->writable = ret == 1 && (pfd.revents & (POLLOUT | POLLERR | POLLHUP)) == POLLOUT;
|
|
|
+ }
|
|
|
|
|
|
return 0;
|
|
|
}
|