Bug 59914 - [patch] poll/unix/kqueue.c IPv6 to IPv4 fallback does not work in serf
Summary: [patch] poll/unix/kqueue.c IPv6 to IPv4 fallback does not work in serf
Status: NEW
Alias: None
Product: APR
Classification: Unclassified
Component: APR (show other bugs)
Version: 1.5.2
Hardware: All FreeBSD
: P2 normal (vote)
Target Milestone: ---
Assignee: Apache Portable Runtime bugs mailinglist
URL: https://bugs.freebsd.org/bugzilla/sho...
Keywords: PatchAvailable
: 59915 59916 59917 (view as bug list)
Depends on:
Blocks:
 
Reported: 2016-07-31 10:27 UTC by ohauer
Modified: 2017-04-25 10:14 UTC (History)
2 users (show)



Attachments
patch to modify apr1 poll() emulation to match behavior expected by serf (2.91 KB, patch)
2016-07-31 10:27 UTC, ohauer
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description ohauer 2016-07-31 10:27:53 UTC
Created attachment 34082 [details]
patch to modify apr1 poll() emulation to match behavior expected by serf

serf depends on the poll emulation in apr returning a POLLERR event if a non-blocking connect() attempt fails in order to trigger an IPv6 -> IPv4 fallback, or a fallback to another address for a multi-homed host.  On FreeBSD, the poll emulation is done using kqueue, and the result returned by the poll() emulation is POLLIN + POLLHUP.

connect(4,{ AF_INET6 [xxxx:xxxx:xxxx:xxxx::xxxx]:80 },28) ERR#36 'Operation now in progress'
gettimeofday({ 1469515046.979614 },0x0)		 = 0 (0x0)
kevent(3,{ 4,EVFILT_READ,EV_ADD,0x0,0x0,0x805491300 },1,0x0,0,0x0) = 0 (0x0)
kevent(3,{ 4,EVFILT_WRITE,EV_ADD,0x0,0x0,0x805491300 },1,0x0,0,0x0) = 0 (0x0)
kevent(3,0x0,0,{ 4,EVFILT_READ,EV_EOF,NOTE_LOWAT|0x3c,0x0,0x805491300 4,EVFILT_WRITE,EV_EOF,NOTE_LOWAT|0x3c,0x8000,0x805491300 },32,{ 0.500000000 }) = 2 (0x2)

When serf sees this, it calls read(), which then fails with ECONNREFUSED (or whatever), which is not even a documented read() errno value.

read(4,0x80549c064,8000)			 ERR#61 'Connection refused'

What that occurs, serf closes the socket an any other addresses are not tried.

The attached patch modifies apr to return what serf expects in the case of a non-blocking connect() failure.  Unfortunately, I did not see an easy way of handling ETIMEDOUT since that error can either be caused by connect failing or after the connection is established.  The poll emulation might need to differentiate between those two cases.

This problem affects users of svn who don't have working IPv6 connectivity to the FreeBSD svn servers.


The original request is in from FreeBSD bugzilla PR 211430 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=211430
Comment 1 ohauer 2016-07-31 10:32:50 UTC
*** Bug 59917 has been marked as a duplicate of this bug. ***
Comment 2 ohauer 2016-07-31 10:36:42 UTC
*** Bug 59916 has been marked as a duplicate of this bug. ***
Comment 3 ohauer 2016-07-31 10:38:01 UTC
*** Bug 59915 has been marked as a duplicate of this bug. ***