skypjack / uvw

Header-only, event based, tiny and easy to use libuv wrapper in modern C++ - now available as also shared/static library!
MIT License
1.82k stars 207 forks source link

Capturing SIGINT #265

Closed smalls12 closed 2 years ago

smalls12 commented 2 years ago

Hello,

Just trying to capture a SIGINT to shut down my app properly.

I was unable to get the following code to send a callback:

    auto loop = uvw::Loop::getDefault();
    auto signal_ = loop->resource<uvw::SignalHandle>();
    signal_->on<uvw::ErrorEvent>(
    [](const uvw::ErrorEvent& event, uvw::SignalHandle &)
    {
        ...
    });

    signal_->on<uvw::CheckEvent>(
    [&](const uvw::CheckEvent& event, uvw::SignalHandle &handle)
    {
        ...
    });

    if(signal_->init())
    {
        signal_->start(2);
    }

The equivalent code in libuv is working for me though

    uv_signal_t *sigint = new uv_signal_t;
    uv_signal_init(uv_default_loop(), sigint);
    uv_signal_start(sigint, on_sigint_received, 2);

any ideas?

Thanks!

skypjack commented 2 years ago

Can I ask you to provide a reproducible example? Also, why do you use a check in the first case while you don't do that in the second case?

smalls12 commented 2 years ago

I can work on providing a full example sure. As for the ErrorEvent/CheckEvent, I was just copying the examples from tests.

smalls12 commented 2 years ago

Here is full example with a chunk for uvw and a chunk for libuv. I expect that the loop simply blocks until a SIGINT is captured.

#include <uvw.hpp>

#include <iostream>
#include <unistd.h>

void on_uv_walk(uv_handle_t* handle, void*)
{
    std::cout << "on_uv_walk()\n";
    uv_close(handle, NULL);
}

void on_sigint_received(uv_signal_t *handle, int)
{
    std::cout << "on_sigint_received()\n";
    int result = uv_loop_close(handle->loop);
    if(result == UV_EBUSY)
    {
        uv_walk(handle->loop, on_uv_walk, NULL);
    }
}

int main()
{
    // ---------------------------------------------------------------
    // uvw
    // ---------------------------------------------------------------
    // auto loop = uvw::Loop::getDefault();
    // auto signal_ = loop->resource<uvw::SignalHandle>();
    // signal_->on<uvw::ErrorEvent>(
    // [](const uvw::ErrorEvent&, uvw::SignalHandle&)
    // {
    //     std::cerr << "uvw::ErrorEvent()\n";
    // });

    // signal_->on<uvw::CheckEvent>(
    // [&](const uvw::CheckEvent&, uvw::SignalHandle&)
    // {
    //     std::cout << "uvw::CheckEvent()\n";
    //     loop->stop();
    // });

    // if(signal_->init())
    // {
    //     std::cout << "signal - initialized?\n";
    //     signal_->start(2);
    // }
    // else
    // {
    //     std::cerr << "signal - error?\n";
    // }

    // std::cout << "start\n";
    // loop->run();
    // std::cout << "stop\n";

    // ---------------------------------------------------------------

    // ---------------------------------------------------------------
    // libuv
    // ---------------------------------------------------------------
    uv_signal_t *sigint = new uv_signal_t;
    uv_signal_init(uv_default_loop(), sigint);
    uv_signal_start(sigint, on_sigint_received, SIGINT);
    uv_loop_t* main_loop = uv_default_loop();
    std::cout << "start\n";
    uv_run(main_loop, UV_RUN_DEFAULT);
    std::cout << "stop\n";
    // ---------------------------------------------------------------

    return 0;
}
smalls12 commented 2 years ago

I can work on providing a full example sure. As for the ErrorEvent/CheckEvent, I was just copying the examples from tests.

Disregard this, I see what you are asking now.

I'm not sure where I saw the return code being checked on init() for uvw but I'm sure I just copied it. I didn't use it for libuv as I was just quickly testing for comparison purposes.

skypjack commented 2 years ago

No, I mean, you have a check handle in one case while you don't have it in the other case. It's like comparing apples and pears, you know. That is why I'm not fully getting what you're doing here. Also, with libuv you're attaching a listener for a sigint while you aren't doing the same when using uvw. So, it's quite obvious that the two examples work differently maybe?

smalls12 commented 2 years ago

I'll just rephrase. Can you point me to an example of how to capture a SIGINT with a listener? Thanks.

skypjack commented 2 years ago

I'm afraid I can't. If there isn't one in the testsuite, then I can't really help.

smalls12 commented 2 years ago

Something has clearly been lost in translation here, I was able to solve the problem on my own switching CheckEvent to SignalEvent. This will capture the SIGINT and run my callback. This behaviour is not in the test suite which lead to my confusion as the test suite only uses CheckEvent.