Ver código fonte

Make Event_socketRead() error rather than panic, if it's impossible. Also: Do not poll WRITABLE because it causes error on OSX.

Caleb James DeLisle 7 meses atrás
pai
commit
df75abe773

+ 1 - 1
interface/ETHInterface_darwin.c

@@ -316,7 +316,7 @@ Er_DEFUN(struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
 
     Socket_makeNonBlocking(ctx->socket);
 
-    Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc);
+    Er(Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc));
 
     Allocator_onFree(alloc, closeSocket, ctx);
 

+ 1 - 1
interface/ETHInterface_linux.c

@@ -279,7 +279,7 @@ Er_DEFUN(struct ETHInterface* ETHInterface_new(struct EventBase* eventBase,
 
     Socket_makeNonBlocking(ctx->socket);
 
-    Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc);
+    Er(Event_socketRead(handleEvent, ctx, ctx->socket, eventBase, alloc));
 
     Er_ret(&ctx->pub);
 }

+ 1 - 0
rust/cjdns_sys/Rffi.h

@@ -158,6 +158,7 @@ int Rffi_isTimeoutActive(const Rffi_TimerTx *timer_tx);
 void Rffi_clearAllTimeouts(Rffi_EventLoop *event_loop);
 
 void Rffi_pollFdReadable(Rffi_FdReadableTx **out,
+                         const char **errout,
                          void (*cb)(void*),
                          void *cb_context,
                          int fd,

+ 16 - 3
rust/cjdns_sys/src/rffi/event_loop/fd_readable.rs

@@ -1,8 +1,10 @@
+use tokio::io::Interest;
+use tokio::io::unix::AsyncFd;
 use super::{Rffi_EventLoop, GCL};
 use crate::cffi::{Allocator_t, Allocator__onFree, Allocator_OnFreeJob};
 use crate::rffi::allocator;
 use std::ffi::c_void;
-use std::os::raw::c_int;
+use std::os::raw::{c_int, c_char};
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::Arc;
 
@@ -31,13 +33,25 @@ pub extern "C" fn fd_readable_on_free(j: *mut Allocator_OnFreeJob) -> c_int {
 #[no_mangle]
 pub extern "C" fn Rffi_pollFdReadable(
     out: *mut *mut Rffi_FdReadableTx,
+    errout: *mut *const c_char,
     cb: unsafe extern "C" fn(*mut c_void),
     cb_context: *mut c_void,
     fd: c_int,
     event_loop: *mut Rffi_EventLoop,
     alloc: *mut Allocator_t,
 ) {
-    // let cb_int = cb_context as u64;
+    let fd = match AsyncFd::with_interest(fd, Interest::READABLE) {
+        Ok(fd) => fd,
+        Err(e) => {
+            let out = allocator::adopt(alloc, format!("Error making AsyncFd: {e}"));
+            let out = unsafe { (*out).as_bytes().as_ptr() } as *const c_char;
+            unsafe {
+                *errout = out;
+            }
+            return;
+        }
+    };
+
     let frc = FdReadableCallback{ cb, cb_context };
 
     let (kill, mut rx_kill) = tokio::sync::mpsc::unbounded_channel();
@@ -62,7 +76,6 @@ pub extern "C" fn Rffi_pollFdReadable(
     }
 
     event_loop.arc_clone().event_job(async move {
-        let fd = tokio::io::unix::AsyncFd::new(fd).unwrap();
         loop {
             tokio::select! {
                 r = fd.readable() => {

+ 3 - 2
util/events/Event.h

@@ -17,13 +17,14 @@
 
 #include "memory/Allocator.h"
 #include "util/events/EventBase.h"
+#include "exception/Er.h"
 #include "util/Linker.h"
 Linker_require("util/events/libuv/Event.c")
 
-void Event_socketRead(void (* const callback)(void* callbackContext),
+Er_DEFUN(void Event_socketRead(void (* const callback)(void* callbackContext),
                       void* const callbackContext,
                       int s,
                       struct EventBase* base,
-                      struct Allocator* alloc);
+                      struct Allocator* alloc));
 
 #endif

+ 9 - 62
util/events/libuv/Event.c

@@ -12,84 +12,31 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
+#include "exception/Er.h"
 #include "rust/cjdns_sys/Rffi.h"
-// #include "util/events/libuv/UvWrapper.h"
 #include "memory/Allocator.h"
 #include "util/events/libuv/EventBase_pvt.h"
 #include "util/events/Event.h"
-#include "util/Identity.h"
 
-#include <stddef.h>
-#include <stdint.h>
-
-// struct Event_pvt
-// {
-//     struct Event pub;
-//     void (* const callback)(void* callbackContext);
-//     void* const callbackContext;
-//     uv_poll_t handler;
-//     struct Allocator* alloc;
-//     Identity
-// };
-
-// static void handleEvent(uv_poll_t* handle, int status, int events)
-// {
-//     struct Event_pvt* event =
-//         Identity_check((struct Event_pvt*) (((char*)handle) - offsetof(struct Event_pvt, handler)));
-
-//     if ((status == 0) && (events & UV_READABLE)) {
-//         event->callback(event->callbackContext);
-//     }
-// }
-
-// static void onClose(uv_handle_t* handle)
-// {
-//     struct Event_pvt* event = Identity_check((struct Event_pvt*) handle->data);
-//     Allocator_free(event->alloc);
-// }
-
-// static int onFree(struct Allocator_OnFreeJob* job)
-// {
-//     struct Event_pvt* event = Identity_check((struct Event_pvt*) job->userData);
-//     event->handler.data = event;
-//     uv_close((uv_handle_t*) &event->handler, onClose);
-//     return 0;
-// }
-
-void Event_socketRead(void (* const callback)(void* callbackContext),
+Er_DEFUN(void Event_socketRead(void (* const callback)(void* callbackContext),
                       void* const callbackContext,
                       int s,
                       struct EventBase* eventBase,
-                      struct Allocator* userAlloc)
+                      struct Allocator* userAlloc))
 {
     struct EventBase_pvt* base = EventBase_privatize(eventBase);
     Rffi_FdReadableTx* out = NULL;
+    const char* errout = NULL;
     Rffi_pollFdReadable(
         &out,
+        &errout,
         callback,
         callbackContext,
         s,
         base->rffi_loop,
         userAlloc);
-
-    // struct EventBase_pvt* base = EventBase_privatize(eventBase);
-    // struct Allocator* alloc = Allocator_child(base->alloc);
-    // struct Event_pvt* out = Allocator_clone(alloc, (&(struct Event_pvt) {
-    //     .callback = callback,
-    //     .callbackContext = callbackContext,
-    //     .alloc = alloc
-    // }));
-    // Identity_set(out);
-
-    // // != 0 check, removed because uv_poll_init always returns 0
-    // uv_poll_init(base->loop, &out->handler, s);
-
-    // // == -1 check, removed because uv_poll_start always returns 0
-    // uv_poll_start(&out->handler, UV_READABLE, handleEvent);
-
-    // out->handler.data = out;
-
-    // Allocator_onFree(userAlloc, onFree, out);
-
-    // return &out->pub;
+    if (errout != NULL) {
+        Er_raise(userAlloc, "Event_socketRead error: %s", errout);
+    }
+    Er_ret();
 }