[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.