Closing libUV Handles Correctly

后端 未结 2 2064
粉色の甜心
粉色の甜心 2021-01-31 06:48

I\'m trying to find out how to fix these memory leaks I\'m getting while running this program with Valgrind. The leaks occur with the two allocations in nShell_client_main

相关标签:
2条回答
  • 2021-01-31 07:01

    I finally figured out how to stop a loop and clean up all handles. I created a bunch of handles and SIGINT signal handle:

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

    When SIGINT is received (Ctrl+C in console is pressed) the on_sigint_received callback is called. The on_sigint_received looks like:

    void on_sigint_received(uv_signal_t *handle, int signum)
    {
        int result = uv_loop_close(handle->loop);
        if (result == UV_EBUSY)
        {
            uv_walk(handle->loop, on_uv_walk, NULL);
        }
    }
    

    It triggers a call back function on_uv_walk:

    void on_uv_walk(uv_handle_t* handle, void* arg)
    {
        uv_close(handle, on_uv_close);
    }
    

    It tries to close each opened libuv handle. Note: that I do not call uv_stop before uv_walk, as mentioned saghul. After on_sigint_received function is called libuv loop continuous the execution and on the next iteration calls on_uv_close for each opened handle. If you call the uv_stop function, then the on_uv_close callback will not be called.

    void on_uv_close(uv_handle_t* handle)
    {
        if (handle != NULL)
        {
            delete handle;
        }
    }
    

    After that libuv do not have opened handles and finishes the loop (exits from uv_run):

    uv_run(uv_default_loop(), UV_RUN_DEFAULT);
    int result = uv_loop_close(uv_default_loop());
    if (result)
    {
        cerr << "failed to close libuv loop: " << uv_err_name(result) << endl;
    }
    else
    {
        cout << "libuv loop is closed successfully!\n";
    }
    
    0 讨论(0)
  • 2021-01-31 07:15

    libuv is not done with a handle until it's close callback is called. That is the exact moment when you can free the handle.

    I see you call uv_loop_close, but you don't check for the return value. If there are still pending handles, it will return UV_EBUSY, so you should check for that.

    If you want to close a loop and close all handles, you need to do the following:

    • Use uv_stop to stop the loop
    • Use uv_walk and call uv_close on all handles which are not closing
    • Run the loop again with uv_run so all close callbacks are called and you can free the memory in the callbacks
    • Call uv_loop_close, it should return 0 now
    0 讨论(0)
提交回复
热议问题