r11487: thanks to make test I noticed a dead lock bug, in the last change,
authorStefan Metzmacher <metze@samba.org>
Thu, 3 Nov 2005 18:38:41 +0000 (18:38 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:45:44 +0000 (13:45 -0500)
this only happens with socket_wrapper as socket_connect() returns NT_STATUS_OK
instead of NT_STATUS_MORE_PROCESSING_REQUIRED, and we missed to replace the
fde event handler...

metze
(This used to be commit f04001f28007ad6bbecdcdf0d1d5887e378d2467)

source4/libcli/wrepl/winsrepl.c

index bf894c6ad0703162de2a20d1acd3e49840936f16..5658a2cc034d76e20adb118ac682ad4f69ac4134 100644 (file)
@@ -433,7 +433,7 @@ static NTSTATUS wrepl_request_wait(struct wrepl_request *req)
        return req->status;
 }
 
-static void wrepl_request_trigger(struct wrepl_request *req);
+static void wrepl_request_trigger(struct wrepl_request *req, NTSTATUS status);
 
 /*
   connect a wrepl_socket to a WINS server
@@ -450,7 +450,7 @@ struct wrepl_request *wrepl_connect_send(struct wrepl_socket *wrepl_socket,
        req->wrepl_socket = wrepl_socket;
        req->state        = WREPL_REQUEST_RECV;
 
-       DLIST_ADD(wrepl_socket->recv_queue, req);
+       DLIST_ADD_END(wrepl_socket->recv_queue, req, struct wrepl_request *);
 
        talloc_set_destructor(req, wrepl_request_destructor);
 
@@ -460,11 +460,21 @@ struct wrepl_request *wrepl_connect_send(struct wrepl_socket *wrepl_socket,
 
        status = socket_connect(wrepl_socket->sock, our_ip, 0, peer_ip, 
                                WINS_REPLICATION_PORT, 0);
+       if (NT_STATUS_IS_OK(status)) {
+               talloc_free(wrepl_socket->fde);
+
+               wrepl_socket->fde = event_add_fd(wrepl_socket->event_ctx, wrepl_socket, 
+                                                socket_get_fd(wrepl_socket->sock), 
+                                                EVENT_FD_WRITE,
+                                                wrepl_handler, wrepl_socket);
+               if (wrepl_socket->fde == NULL) {
+                       status = NT_STATUS_NO_MEMORY;
+               }
+       }
+
        if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
                req->wrepl_socket = wrepl_socket;
-               req->state        = WREPL_REQUEST_ERROR;
-               req->status       = status;
-               wrepl_request_trigger(req);
+               wrepl_request_trigger(req, status);
                return req;
        }
 
@@ -500,9 +510,6 @@ static void wrepl_request_trigger_handler(struct event_context *ev, struct timed
                                          struct timeval t, void *ptr)
 {
        struct wrepl_request *req = talloc_get_type(ptr, struct wrepl_request);
-       struct wrepl_socket *wrepl_socket = req->wrepl_socket;
-       DLIST_REMOVE(wrepl_socket->send_queue, req);
-       DLIST_REMOVE(wrepl_socket->recv_queue, req);
        if (req->async.fn) {
                req->async.fn(req);
        }
@@ -511,8 +518,23 @@ static void wrepl_request_trigger_handler(struct event_context *ev, struct timed
 /*
   trigger an immediate event on a wrepl_request
 */
-static void wrepl_request_trigger(struct wrepl_request *req)
+static void wrepl_request_trigger(struct wrepl_request *req, NTSTATUS status)
 {
+       if (req->state == WREPL_REQUEST_SEND) {
+               DLIST_REMOVE(req->wrepl_socket->send_queue, req);
+       }
+       if (req->state == WREPL_REQUEST_RECV) {
+               DLIST_REMOVE(req->wrepl_socket->recv_queue, req);
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               req->state      = WREPL_REQUEST_ERROR;
+       } else {
+               req->state      = WREPL_REQUEST_DONE;
+       }
+
+       req->status     = status;
+
        /* a zero timeout means immediate */
        event_add_timed(req->wrepl_socket->event_ctx,
                        req, timeval_zero(),
@@ -532,17 +554,19 @@ struct wrepl_request *wrepl_request_send(struct wrepl_socket *wrepl_socket,
        req = talloc_zero(wrepl_socket, struct wrepl_request);
        if (req == NULL) goto failed;
 
+       req->wrepl_socket = wrepl_socket;
+       req->state        = WREPL_REQUEST_SEND;
+
+       DLIST_ADD_END(wrepl_socket->send_queue, req, struct wrepl_request *);
+
+       talloc_set_destructor(req, wrepl_request_destructor);
+
        if (wrepl_socket->dead) {
                req->wrepl_socket = wrepl_socket;
-               req->state        = WREPL_REQUEST_ERROR;
-               req->status       = NT_STATUS_INVALID_CONNECTION;
-               wrepl_request_trigger(req);
+               wrepl_request_trigger(req, NT_STATUS_INVALID_CONNECTION);
                return req;
        }
 
-       req->wrepl_socket = wrepl_socket;
-       req->state        = WREPL_REQUEST_SEND;
-
        wrap.packet = *packet;
        req->status = ndr_push_struct_blob(&req->buffer, req, &wrap,
                                           (ndr_push_flags_fn_t)ndr_push_wrepl_wrap);
@@ -553,10 +577,6 @@ struct wrepl_request *wrepl_request_send(struct wrepl_socket *wrepl_socket,
                NDR_PRINT_DEBUG(wrepl_packet, &wrap.packet);
        }
 
-       DLIST_ADD(wrepl_socket->send_queue, req);
-
-       talloc_set_destructor(req, wrepl_request_destructor);
-
        if (wrepl_socket->request_timeout > 0) {
                req->te = event_add_timed(wrepl_socket->event_ctx, req, 
                                          timeval_current_ofs(wrepl_socket->request_timeout, 0),