summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--bufferevent_sock.c18
-rw-r--r--evutil.c23
-rw-r--r--util-internal.h2
4 files changed, 42 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 68929ee6..b638bf57 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,7 +6,7 @@ Changes in 2.0.3-alpha:
o Try to compile better with MSVC: patches from Brodie Thiesfield
o New evconnlistener_get_fd function to expose a listener's associated socket.
o Expose an ev_socklen_t type for consistent use across platforms.
- o Make bufferevenr_socket_connect() work when the original fd was -1.
+ o Make bufferevent_socket_connect() work when the original fd was -1.
o Fix a bug in bufferevent_socket_connect() when the connection succeeds too quickly.
o Export an evutil_sockaddr_cmp() to compare to sockaddr objects for equality.
o Add a bufferevent_get_enabled() to tell what a bufferevent has been configured to do.
@@ -26,6 +26,7 @@ Changes in 2.0.3-alpha:
o New event_base_got_exit() and event_base_got_break() functions to tell whether an event loop exited because of an event_base_loopexit() or an event_base_loopbreak(). Patch from Ka-Hing Cheung.
o When adding or deleting an event from a non-main thread, only wake up the main thread when its behavior actually needs to change.
o Fix some bugs when using the old evdns interfaces to initialize the evdns module.
+ o Detect errors during bufferevent_connect(). Patch from Christopher Davis.
Changes in 2.0.2-alpha:
diff --git a/bufferevent_sock.c b/bufferevent_sock.c
index f78fc094..b2d0175a 100644
--- a/bufferevent_sock.c
+++ b/bufferevent_sock.c
@@ -192,12 +192,24 @@ bufferevent_writecb(evutil_socket_t fd, short event, void *arg)
goto error;
}
if (bufev_p->connecting) {
+ int c = evutil_socket_finished_connecting(fd);
+
+ if (c == 0)
+ goto done;
+
bufev_p->connecting = 0;
- connected = 1;
- _bufferevent_run_eventcb(bufev, BEV_EVENT_CONNECTED);
- if (!(bufev->enabled & EV_WRITE)) {
+ if (c < 0) {
event_del(&bufev->ev_write);
+ event_del(&bufev->ev_read);
+ _bufferevent_run_eventcb(bufev, BEV_EVENT_ERROR);
goto done;
+ } else {
+ connected = 1;
+ _bufferevent_run_eventcb(bufev, BEV_EVENT_CONNECTED);
+ if (!(bufev->enabled & EV_WRITE)) {
+ event_del(&bufev->ev_write);
+ goto done;
+ }
}
}
diff --git a/evutil.c b/evutil.c
index 9273e966..b41e7819 100644
--- a/evutil.c
+++ b/evutil.c
@@ -297,6 +297,29 @@ err:
return -1;
}
+/* Check whether a socket on which we called connect() is done
+ connecting. Return 1 for connected, 0 for not yet, -1 for error. In the
+ error case, set the current socket errno to the error that happened during
+ the connect operation. */
+int
+evutil_socket_finished_connecting(evutil_socket_t fd)
+{
+ int e;
+ ev_socklen_t elen = sizeof(e);
+
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&e, &elen) < 0)
+ return -1;
+
+ if (e) {
+ if (EVUTIL_ERR_CONNECT_RETRIABLE(e))
+ return 0;
+ EVUTIL_SET_SOCKET_ERROR(e);
+ return -1;
+ }
+
+ return 1;
+}
+
#ifdef WIN32
#define E(code, s) { code, (s " [" #code " ]") }
static struct { int code; const char *msg; } windows_socket_errors[] = {
diff --git a/util-internal.h b/util-internal.h
index 3a842094..f5580ecc 100644
--- a/util-internal.h
+++ b/util-internal.h
@@ -130,6 +130,8 @@ extern const char EVUTIL_TOLOWER_TABLE[];
int evutil_socket_connect(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen);
+int evutil_socket_finished_connecting(evutil_socket_t fd);
+
#ifdef __cplusplus
}
#endif