Print this page
joyent/v8plus#7 v8plus should not hold the event loop open forever

Split Close
Expand all
Collapse all
          --- old/./v8plus_csup.c
          +++ new/./v8plus_csup.c
↓ open down ↓ 23 lines elided ↑ open up ↑
  24   24          v8plus_worker_f vuc_worker;
  25   25          v8plus_completion_f vuc_completion;
  26   26  } v8plus_uv_ctx_t;
  27   27  
  28   28  static STAILQ_HEAD(v8plus_callq_head, v8plus_async_call) _v8plus_callq =
  29   29      STAILQ_HEAD_INITIALIZER(_v8plus_callq);
  30   30  static pthread_mutex_t _v8plus_callq_mtx;
  31   31  static pthread_t _v8plus_uv_event_thread;
  32   32  static uv_async_t _v8plus_uv_async;
  33   33  
       34 +static int _v8plus_eventloop_refcount;
       35 +
  34   36  typedef enum v8plus_async_call_type {
  35   37          ACT_OBJECT_CALL = 1,
  36   38          ACT_OBJECT_RELEASE,
  37   39          ACT_JSFUNC_CALL,
  38   40          ACT_JSFUNC_RELEASE,
       41 +        ACT_EVENTLOOP_RELEASE
  39   42  } v8plus_async_call_type_t;
  40   43  
  41   44  typedef enum v8plus_async_call_flags {
  42   45          ACF_COMPLETED   = 0x01,
  43   46          ACF_NOREPLY     = 0x02
  44   47  } v8plus_async_call_flags_t;
  45   48  
  46   49  
  47   50  typedef struct v8plus_async_call {
  48   51          v8plus_async_call_type_t vac_type;
↓ open down ↓ 65 lines elided ↑ open up ↑
 114  117                  case ACT_OBJECT_RELEASE:
 115  118                          v8plus_obj_rele_direct(vac->vac_cop);
 116  119                          break;
 117  120                  case ACT_JSFUNC_CALL:
 118  121                          vac->vac_return = v8plus_call_direct(
 119  122                              vac->vac_func, vac->vac_lp);
 120  123                          break;
 121  124                  case ACT_JSFUNC_RELEASE:
 122  125                          v8plus_jsfunc_rele_direct(vac->vac_func);
 123  126                          break;
      127 +                case ACT_EVENTLOOP_RELEASE:
      128 +                        v8plus_eventloop_rele_direct();
      129 +                        break;
 124  130                  }
 125  131  
 126  132                  if (vac->vac_flags & ACF_NOREPLY) {
 127  133                          /*
 128  134                           * The caller posted this event and is not sleeping
 129  135                           * on a reply.  Just free the call structure and move
 130  136                           * on.
 131  137                           */
 132  138                          free(vac);
 133  139                          if (vac->vac_lp != NULL)
↓ open down ↓ 163 lines elided ↑ open up ↑
 297  303   */
 298  304  void
 299  305  v8plus_crossthread_init(void)
 300  306  {
 301  307          _v8plus_uv_event_thread = pthread_self();
 302  308          if (uv_async_init(uv_default_loop(), &_v8plus_uv_async,
 303  309              v8plus_async_callback) != 0)
 304  310                  v8plus_panic("unable to initialise uv_async_t");
 305  311          if (pthread_mutex_init(&_v8plus_callq_mtx, NULL) != 0)
 306  312                  v8plus_panic("unable to initialise mutex");
      313 +
      314 +        /*
      315 +         * If we do not unreference the async handle, then its mere
      316 +         * existence will keep the event loop open forever.  If the consumer
      317 +         * _wants_ this behaviour, they may call v8plus_eventloop_hold()
      318 +         * from the event loop thread.
      319 +         */
      320 +        uv_unref((uv_handle_t *)&_v8plus_uv_async);
      321 +}
      322 +
      323 +void
      324 +v8plus_eventloop_hold(void)
      325 +{
      326 +        ++_v8plus_eventloop_refcount;
      327 +        uv_ref((uv_handle_t *)&_v8plus_uv_async);
      328 +}
      329 +
      330 +void
      331 +v8plus_eventloop_rele_direct(void)
      332 +{
      333 +        if (--_v8plus_eventloop_refcount < 1) {
      334 +                _v8plus_eventloop_refcount = 0;
      335 +                uv_unref((uv_handle_t *)&_v8plus_uv_async);
      336 +        }
      337 +}
      338 +
      339 +void
      340 +v8plus_eventloop_rele(void)
      341 +{
      342 +        v8plus_async_call_t *vac;
      343 +
      344 +        if (v8plus_in_event_thread() == B_TRUE) {
      345 +                return (v8plus_eventloop_rele_direct());
      346 +        }
      347 +
      348 +        vac = calloc(1, sizeof (*vac));
      349 +        if (vac == NULL)
      350 +                v8plus_panic("could not allocate async call structure");
      351 +
      352 +        vac->vac_type = ACT_EVENTLOOP_RELEASE;
      353 +        vac->vac_flags = ACF_NOREPLY;
      354 +
      355 +        (void) v8plus_cross_thread_call(vac);
 307  356  }
 308  357  
 309  358  nvlist_t *
 310  359  v8plus_verror(v8plus_errno_t e, const char *fmt, va_list ap)
 311  360  {
 312  361          if (fmt == NULL) {
 313  362                  if (e == V8PLUSERR_NOERROR) {
 314  363                          *_v8plus_errmsg = '\0';
 315  364                  } else {
 316  365                          (void) snprintf(_v8plus_errmsg, V8PLUS_ERRMSG_LEN,
↓ open down ↓ 513 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX