Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intermittent SIGSEGV in cb_multi_socket when using Perl-based Nagios plugin with curl 8.9.1 and perl 5.40 #77

Open
Ysincit opened this issue Aug 14, 2024 · 1 comment

Comments

@Ysincit
Copy link

Ysincit commented Aug 14, 2024

Hi,

I'm experiencing an issue with a Perl-based Nagios plugin that runs repeatedly with the same parameters. Occasionally, it runs concurrently. Approximately every 10th run, the plugin crashes with a SIGSEGV (Segmentation Fault).

Backtrace from Core Dump:

(gdb) bt
#0  0x00007f1976df7b91 in cb_multi_socket () from /usr/local/perlbrew/perls/pl5/lib/site_perl/5.40.0/x86_64-linux-thread-multi-ld/auto/Net/Curl/Curl.so
#1  0x00007f1976d3adab in Curl_multi_pollset_ev () from /usr/lib64/libcurl.so.4
#2  0x00007f1976d07c1b in connc_update_shutdown_ev () from /usr/lib64/libcurl.so.4
#3  0x00007f1976d083d7 in connc_discard_conn () from /usr/lib64/libcurl.so.4
#4  0x00007f1976d3bea7 in multi_done () from /usr/lib64/libcurl.so.4
#5  0x00007f1976d3d100 in multi_runsingle () from /usr/lib64/libcurl.so.4
#6  0x00007f1976d3df34 in curl_multi_perform () from /usr/lib64/libcurl.so.4
#7  0x00007f1976df62bc in XS_Net__Curl__Multi_perform () from /usr/local/perlbrew/perls/pl5/lib/site_perl/5.40.0/x86_64-linux-thread-multi-ld/auto/Net/Curl/Curl.so
#8  0x00007f19775ed438 in Perl_pp_entersub () from /usr/local/perlbrew/perls/pl5/lib/5.40.0/x86_64-linux-thread-multi-ld/CORE/libperl.so
#9  0x00007f1977678d16 in Perl_runops_standard () from /usr/local/perlbrew/perls/pl5/lib/5.40.0/x86_64-linux-thread-multi-ld/CORE/libperl.so
#10 0x00007f1977553488 in perl_run () from /usr/local/perlbrew/perls/pl5/lib/5.40.0/x86_64-linux-thread-multi-ld/CORE/libperl.so
#11 0x0000000000400de2 in main ()

Issue Details:

Upon inspecting the cb_multi_socket function, I noticed that there doesn’t seem to be any error checking that could prevent a SIGSEGV from occurring.

Do you have any suggestions on how this might be mitigated?

Thanks for your help!

@Ysincit
Copy link
Author

Ysincit commented Sep 19, 2024

Hi,
I have tested, adding some consistency checks to cb_multi_socket, and that has ended having SIGSEGV events:

static int
cb_multi_socket(CURL *easy_handle, curl_socket_t s, int what, void *userptr,
                void *socketp)
{
    dTHX;

    perl_curl_multi_t *multi = NULL;
    perl_curl_easy_t *easy = NULL;
    SV *args[5];
    int result;

    /* Check if userptr is NULL */
    if (!userptr) {
        /* warn("cb_multi_socket: userptr is NULL"); */
        return -1;  // Return an appropriate error code
    }
    multi = (perl_curl_multi_t *)userptr;

    /* Retrieve 'easy' pointer and check for errors */
    CURLcode res = curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, (void *)&easy);
    if (res != CURLE_OK || !easy) {
        /* warn("cb_multi_socket: Failed to get easy handle info"); */
        return -1;
    }

    /* Check if the callback is set */
    if (multi->cb[CB_MULTI_SOCKET].func == NULL) {
        /* warn("cb_multi_socket: Callback not set"); */
        return -1;
    }

    /* Prepare arguments for the Perl callback */
    args[0] = SELF2PERL(multi);  // Assumes SELF2PERL handles reference counting
    args[1] = SELF2PERL(easy);   // Assumes SELF2PERL handles reference counting
    args[2] = newSVuv(s);        // Socket number
    args[3] = newSViv(what);     // Event type

    /* Handle socketp */
    if (socketp) {
        args[4] = newSVsv((SV *)socketp);  // Copy the SV pointed to by socketp
    } else {
        args[4] = &PL_sv_undef;
    }

    /* Call the Perl callback */
    result = PERL_CURL_CALL(&multi->cb[CB_MULTI_SOCKET], args);

    /* Clean up SVs to prevent memory leaks */
    SvREFCNT_dec(args[2]);  // newSVuv(s)
    SvREFCNT_dec(args[3]);  // newSViv(what)
    if (socketp) {
        SvREFCNT_dec(args[4]);  // newSVsv((SV *)socketp)
    }
    return result;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant