curl-library
curl_multi_socket_action, epoll and HTTP redirect
Date: Tue, 5 Mar 2013 21:54:10 +0100
Hi,
While trying to use curl_multi_socket_action together with epoll I
noticed that it didn't work in combination with HTTP redirect.
When a socket is first connected, CURLMOPT_SOCKETFUNCTION is called
and the socket is added to the epoll set. Later on when cURL connects
to the HTTP server and sees the redirect it closes the socket (which
makes the kernel remove the socket from the epoll set) and opens a
new. Unfortunately this new socket has the same number as the old, and
thus the socket function callback is never called to add it to the
epoll set.
My current work-around is to keep track of all sockets added in the
socket function callback and also listen to CURLOPT_SOCKOPTFUNCTION to
know when a new socket has been added that wasn't notified in the
socket callback. This works, but seems a bit hackish.
So, have I misunderstood something and it actually works if done right
or is this an issue in cURL?
I'm attaching two files that I have used to reproduce this problem:
httpserver.py - Starts two servers on two different ports where one
redirects to the other.
curlepoll.c - Test program that reproduce the problem.
Output from a test run:
# ./httpserver.py
Connect to http://127.0.0.1:38209 to be redirected to http://127.0.0.1:47067
...
Direct connection works as expected:
# ./curlepoll http://127.0.0.1:47067
Using libcurl/7.29.0 OpenSSL/1.0.1c zlib/1.2.7 libidn/1.25 librtmp/2.3
Hello Port 47067!
bye bye
But connecting to the redirect server hangs:
# ./curlepoll http://127.0.0.1:38209
Using libcurl/7.29.0 OpenSSL/1.0.1c zlib/1.2.7 libidn/1.25 librtmp/2.3
^C
strace shows the problem:
# strace -esocket,connect,close,epoll_ctl ./curlepoll http://127.0.0.1:38209
...
Using libcurl/7.29.0 OpenSSL/1.0.1c zlib/1.2.7 libidn/1.25 librtmp/2.3
...
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(38209),
sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now
in progress)
epoll_ctl(3, EPOLL_CTL_ADD, 4, {EPOLLIN, {u32=4, u64=4}}) = 0
close(4) = 0
...
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(47067),
sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now
in progress)
^C
// Erik
-- Erik Johansson Home Page: http://ejohansson.se/ PGP Key: http://ejohansson.se/erik.asc
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
- text/x-csrc attachment: curlepoll.c
- application/octet-stream attachment: httpserver.py