Hello.

libcurl is freezed in multi mode on SSL urls after it updated from
7.38.0 to 7.52.1 version.

Prompt, please, what I am doing wrong.
Test code attached to the letter.


Linux SMP Debian 4.9.2-2 (2017-01-12) x86_64 GNU/Linux

It's output with libcurl 7.38.0

> ./a.out https://www.google.com/
Using libcurl/7.38.0 OpenSSL/1.0.1t zlib/1.2.8 libidn/1.29
libssh2/1.4.3 librtmp/2.3
>>> timerCallback: timeout: 1 ms
.>>> timerCallback: timeout: 1 ms
.>>> socketCallback: adding fd=5 action=2
>>> timerCallback: timeout: 199 ms
.>>> socketCallback: adding fd=5 action=1
...>>> socketCallback: adding fd=5 action=4
>>> socketCallback: removing fd=5
>>> timerCallback: timeout: 1 ms
.>>> socketCallback: adding fd=6 action=2
>>> timerCallback: timeout: 117 ms
.>>> socketCallback: adding fd=6 action=1
..>>> timerCallback: timeout: 77 ms
...........>>> timerCallback: timeout: -1 ms
.>>> socketCallback: adding fd=6 action=4
>>> socketCallback: removing fd=6
code=200 url=https://www.google.de/?gfe_rd=cr&ei=RKeJWLedHqri8AfZ-YmQDQ
>>> bye bye


It's output with libcurl 7.52.1.
Libcurl freezed.

> ./a.out https://www.google.com/
Using libcurl/7.52.1 OpenSSL/1.0.2j zlib/1.2.8 libidn2/0.14
libpsl/0.16.1 (+libicu/57.1) libssh2/1.7.0 nghttp2/1.17.0 librtmp/2.3
>>> timerCallback: timeout: 0 ms
.>>> timerCallback: timeout: 0 ms
.>>> timerCallback: timeout: 1 ms
.>>> socketCallback: adding fd=4 action=2
>>> timerCallback: timeout: 199 ms
.>>> socketCallback: adding fd=4 action=4
>>> socketCallback: removing fd=4




It's output wiht CURLOPT_VERBOSE

> ./a.out https://www.google.com/
Using libcurl/7.52.1 OpenSSL/1.0.2j zlib/1.2.8 libidn2/0.14
libpsl/0.16.1 (+libicu/57.1) libssh2/1.7.0 nghttp2/1.17.0 librtmp/2.3
>>> timerCallback: timeout: 0 ms
.>>> timerCallback: timeout: 0 ms
.>>> timerCallback: timeout: 1 ms
.>>> timerCallback: timeout: 1 ms
.>>> timerCallback: timeout: 1 ms
*   Trying 172.217.20.164...
* TCP_NODELAY set
.>>> socketCallback: adding fd=4 action=2
>>> timerCallback: timeout: 199 ms
* Connected to www.google.com (172.217.20.164) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
.>>> socketCallback: adding fd=4 action=4
>>> socketCallback: removing fd=4
// cc -lcurl curlepoll.c
// ./a.out https://www.google.com/

#include <assert.h>
#include <curl/curl.h>
#include <poll.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <unistd.h>

void error(const char* string) {
  perror(string);
  exit(1);
}

int epollFd;
int timeout = -1;
struct pollfd pollfd;

int socketCallback(CURL* easy, curl_socket_t fd, int action, void* u, void* s) {
  struct epoll_event event;
  event.events = 0;
  event.data.fd = fd;

  pollfd.fd = fd;
  pollfd.events = 0;
  pollfd.revents = 0;

  printf(">>> %s: adding fd=%d action=%d\n", __func__, fd, action);

  if (action == CURL_POLL_REMOVE) {
    printf(">>> %s: removing fd=%d\n", __func__, fd);

    assert(pollfd.fd == fd);
    pollfd.fd = -1;

    int res = epoll_ctl(epollFd, EPOLL_CTL_DEL, fd, &event);
    if (res == -1 && errno != EBADF)
      error("epoll_ctl(DEL)");
    return 0;
  }

  if (action == CURL_POLL_IN || action == CURL_POLL_INOUT) {
    pollfd.events |= POLLIN;
    event.events |= EPOLLIN;
  }
  if (action == CURL_POLL_OUT || action == CURL_POLL_INOUT) {
    pollfd.events |= POLLOUT;
    event.events |= EPOLLOUT;
  }

  if (event.events != 0) {
    int res = epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &event);
    if (res == -1)
      res = epoll_ctl(epollFd, EPOLL_CTL_MOD, fd, &event);
    if (res == -1)
      error("epoll_ctl(MOD)");
  }

  return 0;
}

int timerCallback(CURLM* multi, long timeout_ms, void* u)
{
  printf(">>> %s: timeout: %ld ms\n", __func__, timeout_ms);
  timeout = timeout_ms;
  return 0;
}

size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata) {
	return size * nmemb;
}

size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata) {
	return size * nitems;
}


int main(int argc, char** argv)
{
  // argv[1] == URL
  // argc[2] == proxi

  pollfd.fd = -1;

  epollFd = epoll_create(1);
  if (epollFd == -1)
    error("epoll_create");

  curl_global_init(CURL_GLOBAL_ALL);
  printf("Using %s\n", curl_version());

  CURL* easy = curl_easy_init();
  curl_easy_setopt(easy, CURLOPT_URL, argv[1]);
  curl_easy_setopt(easy, CURLOPT_FOLLOWLOCATION, 1);
  // curl_easy_setopt(easy, CURLOPT_VERBOSE, 1);

  curl_easy_setopt(easy, CURLOPT_FOLLOWLOCATION, 1);
  curl_easy_setopt(easy, CURLOPT_MAXREDIRS, 5);
  curl_easy_setopt(easy, CURLOPT_COOKIEFILE, "");
  curl_easy_setopt(easy, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
  curl_easy_setopt(easy, CURLOPT_ACCEPT_ENCODING, "gzip");
 
  curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, write_callback);
  curl_easy_setopt(easy, CURLOPT_HEADERFUNCTION, header_callback);

  if (argv[2]) {
    curl_easy_setopt(easy, CURLOPT_PROXY, argv[2]);
  }

  CURLM* multi = curl_multi_init();
  curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, socketCallback);
  curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, timerCallback);

  curl_multi_add_handle(multi, easy);

  int running_handles = 1;
  while (running_handles > 0) {
      // printf(">>> calling epoll_wait\n");
      printf(".");
      struct epoll_event event;
      int res = epoll_wait(epollFd, &event, 1, timeout);
      if (res == -1) {
        error("epoll_wait");
      }
      else if (res == 0) {
        curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
                                 &running_handles);
      }
      else {
        curl_multi_socket_action(multi, event.data.fd, 0,
                                 &running_handles);
      }
  }

  long respcode;
  curl_easy_getinfo(easy, CURLINFO_RESPONSE_CODE, &respcode);

  char * urlp;
  curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &urlp);

  printf("code=%ld url=%s\n", respcode, urlp);

  curl_easy_cleanup(easy);
  curl_multi_cleanup(multi);

  curl_global_cleanup();
  close(epollFd);

  printf(">>> bye bye\n");
  return 0;
}
-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette:   https://curl.haxx.se/mail/etiquette.html

Reply via email to