[Pal] Clean up attrquerybyhdl() for process, socket, pipe, eventfd

Clean up and make uniform the attrquerybyhdl() callback for stream
PAL handles: process, socket, pipe, and eventfd. This includes
using ioctl(FIONREAD) to query the number of bytes available for
reading and using ppoll() to query whether data is available.
This commit is contained in:
Dmitrii Kuvaiskii
2020-01-24 02:16:46 +01:00
committed by Michał Kowalczyk
parent c99497e51b
commit eb77265096
8 changed files with 168 additions and 112 deletions
+19 -12
View File
@@ -135,29 +135,36 @@ static int64_t eventfd_pal_write(PAL_HANDLE handle, uint64_t offset, uint64_t le
/* invoked during poll operation on eventfd from LibOS. */
static int eventfd_pal_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
if (handle->generic.fds[0] == PAL_IDX_POISON)
int ret;
if (handle->eventfd.fd == PAL_IDX_POISON)
return -PAL_ERROR_BADHANDLE;
attr->handle_type = PAL_GET_TYPE(handle);
int efd = handle->eventfd.fd;
int flags = HANDLE_HDR(handle)->flags;
struct pollfd pfd = {.fd = efd, .events = POLLIN, .revents = 0};
int ret = ocall_poll(&pfd, 1, 0);
attr->handle_type = HANDLE_HDR(handle)->type;
attr->nonblocking = handle->eventfd.nonblocking;
attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
attr->writable = HANDLE_HDR(handle)->flags & WRITABLE(0);
/* get number of bytes available for reading */
ret = ocall_fionread(handle->eventfd.fd);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
attr->readable = (ret == 1 && pfd.revents == POLLIN);
attr->disconnected = flags & ERROR(0);
attr->nonblocking = handle->eventfd.nonblocking;
attr->pending_size = ret;
/* query if there is data available for reading */
struct pollfd pfd = {.fd = handle->eventfd.fd, .events = POLLIN, .revents = 0};
ret = ocall_poll(&pfd, 1, 0);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
attr->readable = (ret == 1 && pfd.revents == POLLIN);
/* For future use, so that Linux host kernel can send notifications to user-space apps. App
* receives virtual FD from LibOS, but the Linux-host eventfd is memorized here, such that this
* Linux-host eventfd can be retrieved (by LibOS) during app's ioctl(). */
attr->no_of_fds = 1;
attr->fds[0] = efd;
attr->fds[0] = handle->eventfd.fd;
return 0;
}
+15 -15
View File
@@ -307,37 +307,37 @@ static int pipe_delete(PAL_HANDLE handle, int access) {
}
static int pipe_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
int ret;
if (handle->generic.fds[0] == PAL_IDX_POISON)
return -PAL_ERROR_BADHANDLE;
attr->handle_type = PAL_GET_TYPE(handle);
int read_fd = handle->generic.fds[0];
int flags = HANDLE_HDR(handle)->flags;
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)) {
int ret = ocall_fionread(read_fd);
ret = ocall_fionread(handle->generic.fds[0]);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
attr->pending_size = ret;
attr->writable = flags & (IS_HANDLE_TYPE(handle, pipeprv) ? WRITABLE(1) : WRITABLE(0));
} else {
attr->pending_size = 0;
attr->writable = PAL_FALSE;
attr->writable = HANDLE_HDR(handle)->flags & (IS_HANDLE_TYPE(handle, pipeprv)
? WRITABLE(1) : WRITABLE(0));
}
struct pollfd pfd = {.fd = read_fd, .events = POLLIN, .revents = 0};
int ret = ocall_poll(&pfd, 1, 0);
/* query if there is data available for reading */
struct pollfd pfd = {.fd = handle->generic.fds[0], .events = POLLIN, .revents = 0};
ret = ocall_poll(&pfd, 1, 0);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
attr->readable = (ret == 1 && pfd.revents == POLLIN);
attr->disconnected = flags & ERROR(0);
attr->nonblocking =
IS_HANDLE_TYPE(handle, pipeprv) ? handle->pipeprv.nonblocking : handle->pipe.nonblocking;
return 0;
}
+19 -8
View File
@@ -435,21 +435,32 @@ static int proc_delete (PAL_HANDLE handle, int access)
return 0;
}
static int proc_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
{
static int proc_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
int ret;
if (handle->process.stream == PAL_IDX_POISON)
return -PAL_ERROR_BADHANDLE;
int ret = ocall_fionread(handle->process.stream);
attr->handle_type = HANDLE_HDR(handle)->type;
attr->nonblocking = handle->process.nonblocking;
attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
attr->writable = HANDLE_HDR(handle)->flags & WRITABLE(0);
/* get number of bytes available for reading */
ret = ocall_fionread(handle->process.stream);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
memset(attr, 0, sizeof(PAL_STREAM_ATTR));
attr->pending_size = ret;
attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
attr->readable = (attr->pending_size > 0);
attr->writable = HANDLE_HDR(handle)->flags & WRITABLE(0);
attr->nonblocking = handle->process.nonblocking;
/* query if there is data available for reading */
struct pollfd pfd = {.fd = handle->process.stream, .events = POLLIN, .revents = 0};
ret = ocall_poll(&pfd, 1, 0);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
attr->readable = (ret == 1 && pfd.revents == POLLIN);
return 0;
}
+12 -8
View File
@@ -789,14 +789,16 @@ static int socket_close(PAL_HANDLE handle) {
}
static int socket_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
int ret;
if (handle->sock.fd == PAL_IDX_POISON)
return -PAL_ERROR_BADHANDLE;
attr->handle_type = HANDLE_HDR(handle)->type;
attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
attr->nonblocking = handle->sock.nonblocking;
attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
attr->writable = HANDLE_HDR(handle)->flags & WRITABLE(0);
attr->pending_size = 0; /* fill in later */
attr->socket.linger = handle->sock.linger;
attr->socket.receivebuf = handle->sock.receivebuf;
attr->socket.sendbuf = handle->sock.sendbuf;
@@ -806,20 +808,22 @@ static int socket_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
attr->socket.tcp_keepalive = handle->sock.tcp_keepalive;
attr->socket.tcp_nodelay = handle->sock.tcp_nodelay;
int fd = handle->sock.fd, ret;
/* get number of bytes available for reading (doesn't make sense for listening sockets) */
attr->pending_size = 0;
if (!IS_HANDLE_TYPE(handle, tcpsrv)) {
/* try use ioctl FIONEAD to get the size of socket */
ret = ocall_fionread(fd);
ret = ocall_fionread(handle->sock.fd);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
attr->pending_size = ret;
}
struct pollfd pfd = {.fd = fd, .events = POLLIN, .revents = 0};
ret = ocall_poll(&pfd, 1, 0);
/* query if there is data available for reading */
struct pollfd pfd = {.fd = handle->sock.fd, .events = POLLIN, .revents = 0};
ret = ocall_poll(&pfd, 1, 0);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
attr->readable = (ret == 1 && pfd.revents == POLLIN);
return 0;
+25 -13
View File
@@ -38,6 +38,10 @@
#include "pal_linux_error.h"
#include "pal_security.h"
#ifndef FIONREAD
#define FIONREAD 0x541B
#endif
static inline int eventfd_type(int options) {
int type = 0;
if (options & PAL_OPTION_NONBLOCK)
@@ -133,31 +137,39 @@ static int64_t eventfd_pal_write(PAL_HANDLE handle, uint64_t offset, uint64_t le
return bytes;
}
/* invoked during poll operation on eventfd from LibOS. */
static int eventfd_pal_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
if (handle->generic.fds[0] == PAL_IDX_POISON)
int ret;
int val;
if (handle->eventfd.fd == PAL_IDX_POISON)
return -PAL_ERROR_BADHANDLE;
attr->handle_type = PAL_GET_TYPE(handle);
int efd = handle->eventfd.fd;
int flags = HANDLE_HDR(handle)->flags;
struct pollfd pfd = {.fd = efd, .events = POLLIN, .revents = 0};
struct timespec tp = {0, 0};
int ret = INLINE_SYSCALL(ppoll, 5, &pfd, 1, &tp, NULL, 0);
attr->handle_type = HANDLE_HDR(handle)->type;
attr->nonblocking = handle->eventfd.nonblocking;
attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
attr->writable = HANDLE_HDR(handle)->flags & WRITABLE(0);
/* get number of bytes available for reading */
ret = INLINE_SYSCALL(ioctl, 3, handle->eventfd.fd, FIONREAD, &val);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
attr->readable = (ret == 1 && pfd.revents == POLLIN);
attr->disconnected = flags & ERROR(0);
attr->nonblocking = handle->eventfd.nonblocking;
attr->pending_size = val;
/* query if there is data available for reading */
struct pollfd pfd = {.fd = handle->eventfd.fd, .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));
attr->readable = (ret == 1 && pfd.revents == POLLIN);
/* For future use, so that Linux host kernel can send notifications to user-space apps. App
* receives virtual FD from LibOS, but the Linux-host eventfd is memorized here, such that this
* Linux-host eventfd can be retrieved (by LibOS) during app's ioctl(). */
attr->no_of_fds = 1;
attr->fds[0] = efd;
attr->fds[0] = handle->eventfd.fd;
return 0;
}
+24 -19
View File
@@ -40,6 +40,10 @@ 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);
@@ -336,39 +340,40 @@ static int pipe_delete(PAL_HANDLE handle, int access) {
return 0;
}
#ifndef FIONREAD
#define FIONREAD 0x541B
#endif
static int pipe_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
int ret, val;
int ret;
int val;
if (handle->generic.fds[0] == PAL_IDX_POISON)
return -PAL_ERROR_BADHANDLE;
attr->handle_type = PAL_GET_TYPE(handle);
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;
if (attr->handle_type != pal_type_pipesrv) {
/* 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);
if (IS_ERR(ret)) {
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));
} else {
attr->pending_size = 0;
attr->writable = PAL_FALSE;
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);
attr->readable = (ret == 1 && pfd.revents == POLLIN);
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);
attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
attr->nonblocking =
IS_HANDLE_TYPE(handle, pipeprv) ? handle->pipeprv.nonblocking : handle->pipe.nonblocking;
return 0;
}
+34 -24
View File
@@ -25,28 +25,33 @@
* at creation.
*/
#include "pal_defs.h"
#include "pal_linux_defs.h"
#include "api.h"
#include "pal.h"
#include "pal_debug.h"
#include "pal_defs.h"
#include "pal_error.h"
#include "pal_internal.h"
#include "pal_linux.h"
#include "pal_debug.h"
#include "pal_error.h"
#include "pal_security.h"
#include "pal_linux_defs.h"
#include "pal_rtld.h"
#include "api.h"
#include <linux/sched.h>
#include <linux/types.h>
#include "pal_security.h"
typedef __kernel_pid_t pid_t;
#include <asm/fcntl.h>
#include <sys/socket.h>
#include <asm/errno.h>
#include <asm/fcntl.h>
#include <asm/poll.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/types.h>
#include <sys/socket.h>
#ifndef SEEK_SET
# define SEEK_SET 0
#endif
#ifndef FIONREAD
# define FIONREAD 0x541B
#endif
static inline int create_process_handle (PAL_HANDLE * parent,
PAL_HANDLE * child)
{
@@ -521,29 +526,34 @@ static int proc_delete (PAL_HANDLE handle, int access)
return 0;
}
#ifndef FIONREAD
# define FIONREAD 0x541B
#endif
static int proc_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
{
int ret, val;
static int proc_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
int ret;
int val;
if (handle->process.stream == PAL_IDX_POISON)
return -PAL_ERROR_BADHANDLE;
attr->handle_type = HANDLE_HDR(handle)->type;
attr->nonblocking = handle->process.nonblocking;
attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
attr->writable = HANDLE_HDR(handle)->flags & WRITABLE(0);
/* get number of bytes available for reading */
ret = INLINE_SYSCALL(ioctl, 3, handle->process.stream, FIONREAD, &val);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
attr->handle_type = pal_type_process;
attr->nonblocking = handle->process.nonblocking;
attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
attr->readable = !!val;
attr->writable = HANDLE_HDR(handle)->flags & WRITABLE(0);
attr->runnable = PAL_FALSE;
attr->pending_size = val;
/* query if there is data available for reading */
struct pollfd pfd = {.fd = handle->process.stream, .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));
attr->readable = (ret == 1 && pfd.revents == POLLIN);
return 0;
}
+20 -13
View File
@@ -58,6 +58,10 @@ typedef __kernel_pid_t pid_t;
#define SOL_IPV6 41
#endif
#ifndef FIONREAD
#define FIONREAD 0x541B
#endif
/* 96 bytes is the minimal size of buffer to store a IPv4/IPv6
address */
#define PAL_SOCKADDR_SIZE 96
@@ -969,19 +973,17 @@ static int socket_close(PAL_HANDLE handle) {
return 0;
}
#ifndef FIONREAD
#define FIONREAD 0x541B
#endif
static int socket_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
int ret;
if (handle->sock.fd == PAL_IDX_POISON)
return -PAL_ERROR_BADHANDLE;
attr->handle_type = HANDLE_HDR(handle)->type;
attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
attr->nonblocking = handle->sock.nonblocking;
attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
attr->writable = HANDLE_HDR(handle)->flags & WRITABLE(0);
attr->pending_size = 0; /* fill in later */
attr->socket.linger = handle->sock.linger;
attr->socket.receivebuf = handle->sock.receivebuf;
attr->socket.sendbuf = handle->sock.sendbuf;
@@ -991,20 +993,25 @@ static int socket_attrquerybyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) {
attr->socket.tcp_keepalive = handle->sock.tcp_keepalive;
attr->socket.tcp_nodelay = handle->sock.tcp_nodelay;
int fd = handle->sock.fd, ret, val;
/* get number of bytes available for reading (doesn't make sense for listening sockets) */
attr->pending_size = 0;
if (!IS_HANDLE_TYPE(handle, tcpsrv)) {
/* try use ioctl FIONEAD to get the size of socket */
ret = INLINE_SYSCALL(ioctl, 3, fd, FIONREAD, &val);
int val;
ret = INLINE_SYSCALL(ioctl, 3, handle->sock.fd, FIONREAD, &val);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
attr->pending_size = val;
}
struct pollfd pfd = {.fd = fd, .events = POLLIN, .revents = 0};
/* query if there is data available for reading */
struct pollfd pfd = {.fd = handle->sock.fd, .events = POLLIN, .revents = 0};
struct timespec tp = {0, 0};
ret = INLINE_SYSCALL(ppoll, 5, &pfd, 1, &tp, NULL, 0);
attr->readable = (ret == 1 && pfd.revents == POLLIN);
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);
return 0;
}