Hi all I wrote a simplified program (attached) to demonstrate a problem I'm dealing with. The problem is that libcurl doesn't allow the program to quit because it hangs inside curl_multi_cleanup:
(gdb) bt #0 0x00007ffff7e463f1 in poll () from /lib64/libc.so.6 #1 0x00007ffff7f58a46 in poll (__timeout=1000, __nfds=<optimized out>, __fds=0x7fffffffdc00) at /usr/include/bits/poll2.h:41 #2 Curl_socket_check (readfd0=readfd0@entry=3, readfd1=readfd1@entry=-1, writefd=-1, timeout_ms=<optimized out>, timeout_ms@entry=1000) at ../../lib/select.c:217 #3 0x00007ffff7f66347 in Curl_pp_statemach (pp=pp@entry=0x422370, block=block@entry=true) at ../../lib/pingpong.c:112 #4 0x00007ffff7f61121 in imap_block_statemach (conn=<optimized out>) at ../../lib/imap.c:1365 #5 imap_disconnect (conn=0x421cc0, dead_connection=<optimized out>) at ../../lib/imap.c:1624 #6 0x00007ffff7f3e15d in Curl_disconnect (data=0x4175c0, conn=conn@entry=0x421cc0, dead_connection=dead_connection@entry=false) at ../../lib/url.c:781 #7 0x00007ffff7f6e8f3 in Curl_conncache_close_all_connections ( connc=connc@entry=0x409d70) at ../../lib/conncache.c:573 #8 0x00007ffff7f535d1 in curl_multi_cleanup (multi=multi@entry=0x409c60) at ../../lib/multi.c:2244 #9 0x000000000040139a in main (argc=<optimized out>, argv=<optimized out>) at curl_imap_teardown_issue.c:89 The program logs in to an imaps:// server (using CURLOPT_CONNECT_ONLY), then enters idle mode using curl_easy_send and receives answer using curl_easy_recv. Then sleeps for a few seconds and tries to clean up everything and quit. I followed the order given at https://curl.haxx.se/libcurl/c/curl_multi_cleanup.html but still curl_multi_cleanup() doesn't exit for a long time. The issue occurs on libcurl-7.61.1 as well as on latest release curl-7.64.1. Am I doing something wrong, or is it a bug? --
#include <stdio.h> #include <assert.h> #include <time.h> #include <curl/curl.h> static const char cmd[] = "A1 IDLE\n"; static char buf[1024]; int main(int argc, char **argv) { CURLM *mcurl; CURL *curl; int mrun, sock = CURL_SOCKET_BAD; time_t start = time(NULL); int state = 0; ssize_t pos = 0; if (argc < 2) { fprintf(stderr, "Usage: %s imaps://mailserver.com u...@mailserver.com password\n", argv[0]); return 1; } assert((mcurl = curl_multi_init())); assert((curl = curl_easy_init())); assert(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L) == CURLE_OK); assert(curl_easy_setopt(curl, CURLOPT_URL, argv[1]) == CURLE_OK); if (argc > 2) assert(curl_easy_setopt(curl, CURLOPT_USERNAME, argv[2]) == CURLE_OK); if (argc > 3) assert(curl_easy_setopt(curl, CURLOPT_PASSWORD, argv[3]) == CURLE_OK); assert(curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L) == CURLE_OK); //assert(curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, 1L) == CURLE_OK); assert(curl_multi_add_handle(mcurl, curl) == CURLM_OK); while (time(NULL) - start < 5) { struct curl_waitfd waitfd; assert(curl_multi_perform(mcurl, &mrun) == CURLM_OK); for (;;) { int i; struct CURLMsg *m = curl_multi_info_read(mcurl, &i); if (!m) break; if (m->msg == CURLMSG_DONE && m->easy_handle == curl) { assert(curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sock) == CURLE_OK); assert(sock != CURL_SOCKET_BAD); } } if (sock >= 0) { waitfd.events = state ? CURL_WAIT_POLLIN : CURL_WAIT_POLLOUT; waitfd.revents = 0; assert(curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sock) == CURLE_OK); waitfd.fd = sock; } assert(curl_multi_wait(mcurl, &waitfd, sock < 0 ? 0 : 1, 5000, &mrun) == CURLM_OK); if (sock >= 0 && (waitfd.revents & waitfd.events)) { size_t len = 0; if (!state) { assert(curl_easy_send(curl, cmd + pos, sizeof(cmd) - 1 - pos, &len) == CURLE_OK); if (len > 0) pos += len; else pos = 0; if (pos == sizeof(cmd) - 1) { state++; pos = 0; } } else if (pos < sizeof(buf)) { assert(curl_easy_recv(curl, buf + pos, sizeof(buf) - pos, &len) == CURLE_OK); if (len > 0) pos += len; } if (len <= 0) sock = -1; } } if (state) { fwrite(buf, pos, 1, stdout); putchar('\n'); } assert(curl_multi_remove_handle(mcurl, curl) == CURLM_OK); curl_easy_cleanup(curl); curl_multi_cleanup(mcurl); return 0; }
------------------------------------------------------------------- Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library Etiquette: https://curl.haxx.se/mail/etiquette.html