[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [Libevent-users] evhttp client error handling
Hi Patrick,
It looks like that you don't have ipv6 support, maybe kernel module
don't loaded.
Try to test like this
$ ls /proc/net/if_inet6
Here is more info how to test ipv6 support in linux
http://www.tldp.org/HOWTO/Linux+IPv6-HOWTO/systemcheck-kernel.html
I clone you repository, apply you patch, and the server is started.
netstat shows:
$ netstat -anp | fgrep https
tcp6 0 0 :::8421 :::*
LISTEN 15079/https-server
What about IPv6 and IPv4 at the same time
There is socket option: IPV6_V6ONLY (ipv6 (7)), default value is 1.
But you can't set this option right using libevent, but you can set
default value for this option using using proc:
$ echo 0 | sudo tee -a /proc/sys/net/ipv6/bindv6only
But after this you program have segfault
On Sat, Jan 26, 2013 at 6:29 AM, Patrick Pelletier
<ppelletier@xxxxxxxxxx> wrote:
> I've put my sample code up on github, so we have something concrete to talk
> about:
>
> https://github.com/ppelleti/https-example
>
> However, I think I've figured out why I'm getting the ECONNREFUSED: it's for
> the obvious reason, that my server is only running on IPv4, and not on IPv6.
> I was led astray by the comment saying that ECONNREFUSED was expected when
> connecting to localhost, but I don't think that comment is relevant to my
> situation. I'm getting a perfectly legitimate ECONNREFUSED, because my
> server is only running on 127.0.0.1, and isn't running on ::1.
>
> I was also led astray by the fact that curl seems to connect to IPv4 first
> (or maybe it tries both?), while evhttp tries IPv6 first, and gives up if it
> doesn't work. So curl was working fine for me, but it was using IPv4 even
> when I gave it the name "localhost". However, if I give curl the "-6"
> option, then it doesn't work either. That's when I realized my server
> wasn't running on ::1.
>
> So, I tried running my server on IPv6 instead of IPv4, by making this
> change:
>
> --- a/https-server.c
> +++ b/https-server.c
> @@ -230,7 +230,7 @@ static int serve_some_http (void)
> evhttp_set_gencb (http, send_document_cb, NULL);
>
> /* Now we tell the evhttp what port to listen on */
> - handle = evhttp_bind_socket_with_handle (http, "0.0.0.0", port);
> + handle = evhttp_bind_socket_with_handle (http, "::0", port);
> if (! handle)
> { fprintf (stderr, "couldn't bind to port %d. Exiting.\n", (int) port);
> return 1;
>
> but then the server fails to run, like this:
>
> ppelletier@chives:~/src/https-example$ ./https-server
> Using OpenSSL version "OpenSSL 1.0.1c 10 May 2012"
> and libevent version "2.1.2-alpha-dev"
> Loading certificate chain from 'server-certificate-chain.pem'
> and private key from 'server-private-key.pem'
> [warn] getaddrinfo: address family for nodename not supported
> couldn't bind to port 8421. Exiting.
>
> So, I'm not sure what's going on there. And anyway, I don't really want to
> run the server on just IPv6; I want it to answer on both IPv4 and IPv6. But
> I don't know if there's a way to do that other than running two http
> servers.
>
> --Patrick
>
>
>
> On 01/23/2013 10:18 PM, Azat Khuzhin wrote:
>>
>> What about your ECONNREFUSED, does you have something like this, if
>> you run "curl -v --data CORRECT_POST_DATA_HERE HOST" ?
>> (it seems that you try POST request: client_do_post)
>> Does you server ("localhost") have the valid HTTP answer?
>>
>> Why it couldn't get response after first request.
>> Could you post you code somewhere? If you don't want to show all of
>> it, you could write 20-40 lines, that can reproduce this problem.
>>
>> About retries: could you send backtrace when this messages are printed?
>>
>>
>> Thanks.
>>
>> On Thu, Jan 24, 2013 at 7:36 AM, Patrick Pelletier
>> <ppelletier@xxxxxxxxxx> wrote:
>>>
>>> On 01/22/2013 02:54 PM, Azat Khuzhin wrote:
>>>
>>>> Could you try to test my patch
>>>>
>>>>
>>>> https://github.com/azat/libevent/commit/71e709c7829275a594f767b27468b1b52e8b5bb9.patch
>>>>
>>>> and write if it works for you?
>>>
>>>
>>>
>>> Thanks, I think that's a step in the right direction.
>>>
>>> However, I'm still having trouble. My callback is getting called with
>>> evhttp_request_get_response_code (req) == 0. (i. e. something went
>>> wrong,
>>> but we don't know what. That gets back to the original topic of this
>>> thread, that evhttp is very vague about what errors happened.)
>>>
>>> Here's the backtrace when my callback gets called:
>>>
>>> #0 request_finished (req=0x758df0, arg=0x7fffffffe070) at
>>> client-http.c:46
>>> #1 0x00007ffff7628b58 in evhttp_connection_cb_cleanup (evcon=0x758280)
>>> at http.c:1319
>>> #2 0x00007ffff7629050 in evhttp_connection_cb (bufev=0x7579b0, what=33,
>>> arg=0x758280) at http.c:1462
>>> #3 0x00007ffff75f93d0 in bufferevent_run_deferred_callbacks_locked (
>>> cb=0x757b50, arg=0x7579b0) at bufferevent.c:161
>>> #4 0x00007ffff7604389 in event_process_active_single_queue
>>> (base=0x756790,
>>> activeq=0x754080, max_to_process=2147483647, endtime=0x0) at
>>> event.c:1476
>>> #5 0x00007ffff760464e in event_process_active (base=0x756790) at
>>> event.c:1538
>>> #6 0x00007ffff7604db2 in event_base_loop (base=0x756790, flags=0)
>>> at event.c:1761
>>> #7 0x000000000040dd49 in client_do_post (host=0x4e9aa8 "localhost",
>>> port=8421, passcode=0x4e9ab2 "R23") at client-http.c:246
>>> #8 0x000000000040ddba in main (argc=1, argv=0x7fffffffe288)
>>> at client-main.c:30
>>>
>>> (all the line numbers correspond to your "fix-http-for-ipv6" branch,
>>> commit
>>> 71e709c7829275a594f767b27468b1b52e8b5bb9)
>>>
>>> It appears that what's happening is the "if (errno == ECONNREFUSED) goto
>>> cleanup;" in http.c:1409 is being triggered. The comment right above it
>>> says:
>>>
>>> /* some operating systems return ECONNREFUSED immediately
>>> * when connecting to a local address. the cleanup is going
>>> * to reschedule this function call.
>>> */
>>>
>>> Obviously my operating system (Ubuntu 10.04 LTS) must be one of these
>>> operating systems. But then I was curious why the cleanup wasn't
>>> rescheduling the function call, the way the comment said it would.
>>>
>>> It turns out that at the top of evhttp_connection_cb_cleanup is:
>>>
>>> if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max)
>>>
>>> and that was the problem. retry_max defaults to 0, which means that it
>>> actually won't retry the way the comment said it would. This seems like
>>> a
>>> poor default, given that the code is relying on a retry being possible,
>>> for
>>> the ECONNREFUSED case.
>>>
>>> So, I tried fixing this in my client code by calling:
>>>
>>> evhttp_connection_set_retries (conn, 3);
>>>
>>> However, now what happens is I get:
>>>
>>> [warn] Epoll ADD(1) on fd 7 failed. Old events were 0; read change was 1
>>> (add); write change was 0 (none): Bad file descriptor
>>> [warn] Epoll ADD(4) on fd 7 failed. Old events were 0; read change was 0
>>> (none); write change was 1 (add): Bad file descriptor
>>>
>>> and my http request still fails. But that's as far as I've gotten in
>>> debugging it, though.
>>>
>>> But thanks for your patch! I think that will be part of the solution;
>>> I'm
>>> just running into other evhttp issues now (the ECONNREFUSED and retry
>>> thing).
>>>
>>> --Patrick
>>>
>>
>>
>>
>
--
Azat Khuzhin
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users in the body.