Exemplo n.º 1
0
static struct sol_mainloop_source *
event_create_source(sd_event *event)
{
    struct sol_mainloop_source *source;
    struct source_ctx *ctx;

    ctx = malloc(sizeof(*ctx));
    SOL_NULL_CHECK(ctx, NULL);

    ctx->event = sd_event_ref(event);

    ctx->fd_handler = sol_fd_add(sd_event_get_fd(event),
        SOL_FD_FLAGS_IN | SOL_FD_FLAGS_HUP | SOL_FD_FLAGS_ERR,
        on_sd_event_fd, ctx);
    SOL_NULL_CHECK_GOTO(ctx->fd_handler, error_fd);

    source = sol_mainloop_add_source(&source_type, ctx);
    SOL_NULL_CHECK_GOTO(source, error_source);

    return source;

error_source:
    sol_fd_del(ctx->fd_handler);
error_fd:
    sd_event_unref(ctx->event);
    free(ctx);
    return NULL;
}
Exemplo n.º 2
0
int
hijack_main_loop()
{
    int returnValue;
    uv_loop_t *uv_loop = NULL;

    SOL_DBG("Entering with state %s", RESOLVE_MAINLOOP_STATE(mainloopState));
    if (mainloopState == MAINLOOP_HIJACKED ||
        mainloopState == MAINLOOP_HIJACKING_STARTED) {
        return 0;
    }

    uv_loop = uv_default_loop();

    // The actual hijacking starts here, inspired by node-gtk. The plan:
    // 1. uv has two ways of letting us know that it needs to run its loop. One
    //    is that its backend timeout is >= 0, and the other is a file
    //    descriptor which can become readable/writable/errored. So, attach a
    //    source to the soletta main loop which will run the uv main loop in
    //    a non-blocking fashion. Also attach a file descriptor watch via which
    //    uv can signal that it needs to run an iteration.
    // 2. Attach an idler to the uv main loop and call sol_run() from it when
    //    it first runs. This interrupts the uv main loop, because sol_run()
    //    doesn't return but, since we've already added the above sources to
    //    the soletta main loop in the first step, the source or the file
    //    descriptor watch will end up running one non-blocking iteration of
    //    the uv main loop which, in turn, will recursively call the idler we
    //    added. At that point, the idler can remove itself from the uv main
    //    loop. After that, only the soletta main loop runs, but it runs an
    //    iteration of the uv main loop in a non-blocking fashion whenever the
    //    uv main loop signals to the soletta main loop via the attached
    //    source or the attached file descriptor watch.
    // 3. Attach a token handle to the uv main loop which represents all
    //    soletta open handles. This is necessary because the uv main loop
    //    would otherwise quit when it runs out of its own handles. We remove
    //    this token handle when we release the uv main loop so that if, at
    //    that point, it has no more handles, it is free to cause the node.js
    //    process to quit.

    // We allocate the various needed structures only once. After that, we
    // reuse them. We never free them, even if we release the uv main loop.
    if (!uv_loop_source) {
        uv_loop_source = sol_mainloop_add_source(&uv_loop_source_funcs,
            uv_loop);
        if (!uv_loop_source) {
            return -ENOMEM;
        }
    }

    if (!uv_loop_fd) {
        uv_loop_fd = sol_fd_add(uv_backend_fd(uv_loop),
            SOL_FD_FLAGS_IN | SOL_FD_FLAGS_OUT | SOL_FD_FLAGS_ERR,
            uv_loop_fd_changed, uv_loop);
        if (!uv_loop_fd) {
            return -ENOMEM;
        }
    }

    returnValue = uv_prepare_init(uv_loop, &uv_token_handle);
    if (returnValue) {
        return returnValue;
    }

    returnValue = uv_idle_init(uv_loop, &uv_idle);
    if (returnValue) {
        return returnValue;
    }

    SOL_DBG("Starting token handle");
    returnValue = uv_prepare_start(&uv_token_handle, uv_token_callback);
    if (returnValue) {
        return returnValue;
    }

    SOL_DBG("Starting idler");
    returnValue = uv_idle_start(&uv_idle, uv_idle_callback);
    if (returnValue) {
        return returnValue;
    }

    mainloopState = MAINLOOP_HIJACKING_STARTED;
    return 0;
}