Skip to content

Fix for #21547 breaks expectations of users of curl_multi_perform with curl_multi_wakeup #22272

Description

@xokdvium

I did this

Basically, 2a2104f has caused some unfortunate breakage in Nix and forks thereof upon update to 8.21.

Since the commit linked above, curl_multi_perform now swallows wakeups and this leads either excessive waiting for a timeout (or in case of Lix, blocking on curl_multi_poll forever).

Single-threaded example:

#include <curl/curl.h>

int main() {
  curl_global_init(CURL_GLOBAL_ALL);

  auto curlm = curl_multi_init();

  int running = 0;
  CURLMcode mc;

  curl_multi_wakeup(curlm);
  curl_multi_perform(curlm, &running);
  curl_multi_poll(curlm, nullptr, 0, INT_MAX, nullptr);
}

Since 2a2104f:

eventfd2(0, EFD_CLOEXEC|EFD_NONBLOCK)   = 3
close(4)                                = 0
write(3, "\1\0\0\0\0\0\0\0", 8)         = 8
read(3, "\1\0\0\0\0\0\0\0", 64)         = 8
read(3, 0x7ffcfe6afd70, 64)             = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=3, events=POLLIN}], 1, 2147483647

And we never exit the poll.
In <8.21 the wakeup would not be consumed in perform and we'd happily exit:

eventfd2(0, EFD_CLOEXEC|EFD_NONBLOCK)   = 3
close(4)                                = 0
write(3, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}], 1, 2147483647) = 1 ([{fd=3, revents=POLLIN}])

Our use is pretty much the same as documented in https://curl.se/libcurl/c/curl_multi_wakeup.html.

I expected the following

Either the new behavior is deemed to be correct, or a bug to be fixed.
Currently we are working around this issue (?) in NixOS/nix#16090.

curl/libcurl version

curl 8.21.0

operating system

Linux blahblah 6.18.38 #1-NixOS SMP PREEMPT_DYNAMIC .... x86_64 GNU/Linux

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions