Browse Source

[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.
Dmitrii Kuvaiskii 4 years ago
parent
commit
eb77265096

+ 17 - 10
Pal/src/host/Linux-SGX/db_eventfd.c

@@ -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);
+    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);
 
-    int efd = handle->eventfd.fd;
-    int flags = HANDLE_HDR(handle)->flags;
+    /* get number of bytes available for reading */
+    ret = ocall_fionread(handle->eventfd.fd);
+    if (IS_ERR(ret))
+        return unix_to_pal_error(ERRNO(ret));
 
-    struct pollfd pfd = {.fd = efd, .events = POLLIN, .revents = 0};
-    int ret = ocall_poll(&pfd, 1, 0);
+    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);
-    attr->disconnected = flags & ERROR(0);
-    attr->nonblocking  = handle->eventfd.nonblocking;
+    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
Pal/src/host/Linux-SGX/db_pipes.c

@@ -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
Pal/src/host/Linux-SGX/db_process.c

@@ -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
Pal/src/host/Linux-SGX/db_sockets.c

@@ -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;

+ 24 - 12
Pal/src/host/Linux/db_eventfd.c

@@ -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;
+    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);
 
-    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);
+    /* 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->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);
-    attr->disconnected = flags & ERROR(0);
-    attr->nonblocking  = handle->eventfd.nonblocking;
+    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
Pal/src/host/Linux/db_pipes.c

@@ -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;
 }
 

+ 33 - 23
Pal/src/host/Linux/db_process.c

@@ -25,28 +25,33 @@
  * at creation.
  */
 
-#include "pal_defs.h"
-#include "pal_linux_defs.h"
+#include "api.h"
 #include "pal.h"
-#include "pal_internal.h"
-#include "pal_linux.h"
 #include "pal_debug.h"
+#include "pal_defs.h"
 #include "pal_error.h"
-#include "pal_security.h"
+#include "pal_internal.h"
+#include "pal_linux.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/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>
-#include <asm/errno.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
Pal/src/host/Linux/db_sockets.c

@@ -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;
 }