summaryrefslogtreecommitdiff
path: root/lib/async_req
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2009-05-24 13:14:12 +0200
committerVolker Lendecke <vl@samba.org>2009-05-24 13:50:54 +0200
commit9de2efaa5b197c46508c36f50bbe6c5026f2953a (patch)
tree75fe11baf9f8b8ef802a118ba07948d01817c28e /lib/async_req
parent4906d7fc679210555871bcb080e504fcc11734c6 (diff)
downloadsamba-9de2efaa5b197c46508c36f50bbe6c5026f2953a.tar.gz
samba-9de2efaa5b197c46508c36f50bbe6c5026f2953a.tar.bz2
samba-9de2efaa5b197c46508c36f50bbe6c5026f2953a.zip
Change async_connect to use connect instead of getsockopt to get the error
On my Linux box, this is definitely the more reliable strategy with unix domain sockets, and according to my tests it also works correctly with TCP sockets.
Diffstat (limited to 'lib/async_req')
-rw-r--r--lib/async_req/async_sock.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c
index d7f31768ef..fe71b29117 100644
--- a/lib/async_req/async_sock.c
+++ b/lib/async_req/async_sock.c
@@ -167,6 +167,8 @@ struct async_connect_state {
int result;
int sys_errno;
long old_sockflags;
+ socklen_t address_len;
+ struct sockaddr_storage address;
};
static void async_connect_connected(struct tevent_context *ev,
@@ -209,6 +211,13 @@ struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx,
state->fd = fd;
state->sys_errno = 0;
+ state->address_len = address_len;
+ if (address_len > sizeof(state->address)) {
+ errno = EINVAL;
+ goto post_errno;
+ }
+ memcpy(&state->address, address, address_len);
+
state->old_sockflags = fcntl(fd, F_GETFL, 0);
if (state->old_sockflags == -1) {
goto post_errno;
@@ -270,8 +279,6 @@ static void async_connect_connected(struct tevent_context *ev,
struct async_connect_state *state =
tevent_req_data(req, struct async_connect_state);
- TALLOC_FREE(fde);
-
/*
* Stevens, Network Programming says that if there's a
* successful connect, the socket is only writable. Upon an
@@ -279,20 +286,23 @@ static void async_connect_connected(struct tevent_context *ev,
*/
if ((flags & (TEVENT_FD_READ|TEVENT_FD_WRITE))
== (TEVENT_FD_READ|TEVENT_FD_WRITE)) {
- int sockerr;
- socklen_t err_len = sizeof(sockerr);
-
- if (getsockopt(state->fd, SOL_SOCKET, SO_ERROR,
- (void *)&sockerr, &err_len) == 0) {
- errno = sockerr;
+ int ret;
+
+ ret = connect(state->fd,
+ (struct sockaddr *)(void *)&state->address,
+ state->address_len);
+ if (ret == 0) {
+ TALLOC_FREE(fde);
+ tevent_req_done(req);
+ return;
}
- state->sys_errno = errno;
-
- DEBUG(10, ("connect returned %s\n", strerror(errno)));
-
- fcntl(state->fd, F_SETFL, state->old_sockflags);
- tevent_req_error(req, state->sys_errno);
+ if (errno == EINPROGRESS) {
+ /* Try again later, leave the fde around */
+ return;
+ }
+ TALLOC_FREE(fde);
+ tevent_req_error(req, errno);
return;
}