quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

ares_event_wake_pipe.c (4189B)


      1 /* MIT License
      2  *
      3  * Copyright (c) 2024 Brad House
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a copy
      6  * of this software and associated documentation files (the "Software"), to deal
      7  * in the Software without restriction, including without limitation the rights
      8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      9  * copies of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  * SPDX-License-Identifier: MIT
     25  */
     26 #include "ares_private.h"
     27 #include "ares_event.h"
     28 
     29 #if defined(HAVE_PIPE) && defined(CARES_THREADS)
     30 
     31 #  ifdef HAVE_UNISTD_H
     32 #    include <unistd.h>
     33 #  endif
     34 #  ifdef HAVE_FCNTL_H
     35 #    include <fcntl.h>
     36 #  endif
     37 
     38 typedef struct {
     39   int filedes[2];
     40 } ares_pipeevent_t;
     41 
     42 static void ares_pipeevent_destroy(ares_pipeevent_t *p)
     43 {
     44   if (p->filedes[0] != -1) {
     45     close(p->filedes[0]);
     46   }
     47   if (p->filedes[1] != -1) {
     48     close(p->filedes[1]);
     49   }
     50 
     51   ares_free(p);
     52 }
     53 
     54 static void ares_pipeevent_destroy_cb(void *arg)
     55 {
     56   ares_pipeevent_destroy(arg);
     57 }
     58 
     59 static ares_pipeevent_t *ares_pipeevent_init(void)
     60 {
     61   ares_pipeevent_t *p = ares_malloc_zero(sizeof(*p));
     62   if (p == NULL) {
     63     return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
     64   }
     65 
     66   p->filedes[0] = -1;
     67   p->filedes[1] = -1;
     68 
     69 #  ifdef HAVE_PIPE2
     70   if (pipe2(p->filedes, O_NONBLOCK | O_CLOEXEC) != 0) {
     71     ares_pipeevent_destroy(p); /* LCOV_EXCL_LINE: UntestablePath */
     72     return NULL;               /* LCOV_EXCL_LINE: UntestablePath */
     73   }
     74 #  else
     75   if (pipe(p->filedes) != 0) {
     76     ares_pipeevent_destroy(p);
     77     return NULL;
     78   }
     79 
     80 #    ifdef O_NONBLOCK
     81   {
     82     int val;
     83     val = fcntl(p->filedes[0], F_GETFL, 0);
     84     if (val >= 0) {
     85       val |= O_NONBLOCK;
     86     }
     87     fcntl(p->filedes[0], F_SETFL, val);
     88 
     89     val = fcntl(p->filedes[1], F_GETFL, 0);
     90     if (val >= 0) {
     91       val |= O_NONBLOCK;
     92     }
     93     fcntl(p->filedes[1], F_SETFL, val);
     94   }
     95 #    endif
     96 
     97 #    ifdef FD_CLOEXEC
     98   fcntl(p->filedes[0], F_SETFD, FD_CLOEXEC);
     99   fcntl(p->filedes[1], F_SETFD, FD_CLOEXEC);
    100 #    endif
    101 #  endif
    102 
    103 #  ifdef F_SETNOSIGPIPE
    104   fcntl(p->filedes[0], F_SETNOSIGPIPE, 1);
    105   fcntl(p->filedes[1], F_SETNOSIGPIPE, 1);
    106 #  endif
    107 
    108   return p;
    109 }
    110 
    111 static void ares_pipeevent_signal(const ares_event_t *e)
    112 {
    113   const ares_pipeevent_t *p;
    114 
    115   if (e == NULL || e->data == NULL) {
    116     return; /* LCOV_EXCL_LINE: DefensiveCoding */
    117   }
    118 
    119   p = e->data;
    120   (void)write(p->filedes[1], "1", 1);
    121 }
    122 
    123 static void ares_pipeevent_cb(ares_event_thread_t *e, ares_socket_t fd,
    124                               void *data, ares_event_flags_t flags)
    125 {
    126   unsigned char           buf[32];
    127   const ares_pipeevent_t *p = NULL;
    128 
    129   (void)e;
    130   (void)fd;
    131   (void)flags;
    132 
    133   if (data == NULL) {
    134     return; /* LCOV_EXCL_LINE: DefensiveCoding */
    135   }
    136 
    137   p = data;
    138 
    139   while (read(p->filedes[0], buf, sizeof(buf)) == sizeof(buf)) {
    140     /* Do nothing */
    141   }
    142 }
    143 
    144 ares_event_t *ares_pipeevent_create(ares_event_thread_t *e)
    145 {
    146   ares_event_t     *event = NULL;
    147   ares_pipeevent_t *p     = NULL;
    148   ares_status_t     status;
    149 
    150   p = ares_pipeevent_init();
    151   if (p == NULL) {
    152     return NULL;
    153   }
    154 
    155   status = ares_event_update(&event, e, ARES_EVENT_FLAG_READ, ares_pipeevent_cb,
    156                              p->filedes[0], p, ares_pipeevent_destroy_cb,
    157                              ares_pipeevent_signal);
    158   if (status != ARES_SUCCESS) {
    159     ares_pipeevent_destroy(p); /* LCOV_EXCL_LINE: DefensiveCoding */
    160     return NULL;               /* LCOV_EXCL_LINE: DefensiveCoding */
    161   }
    162 
    163   return event;
    164 }
    165 
    166 #endif