s3-g_lock: Make g_lock_lock more robust
authorVolker Lendecke <vl@samba.org>
Fri, 10 Aug 2012 15:00:38 +0000 (17:00 +0200)
committerChristian Ambach <ambi@samba.org>
Thu, 16 Aug 2012 17:44:00 +0000 (19:44 +0200)
If for some reason the cleanup of dbwrap_watch_send does not work
properly, we might starve indefinitely. Make the lock routine more
robust by retrying every 5-10 seconds. g_lock_trylock will clean up
orphaned entries.

Signed-off-by: Christian Ambach <ambi@samba.org>
Autobuild-User(master): Christian Ambach <ambi@samba.org>
Autobuild-Date(master): Thu Aug 16 19:44:00 CEST 2012 on sn-devel-104

source3/lib/g_lock.c

index f7fe3db73189a61444c99f34d27bfc12cb52ab51..4535b355690a64fc418ed307a24a3e28960f0a91 100644 (file)
@@ -227,6 +227,12 @@ struct tevent_req *g_lock_lock_send(TALLOC_CTX *mem_ctx,
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
+       if (!tevent_req_set_endtime(
+                   subreq, state->ev,
+                   timeval_current_ofs(5 + sys_random() % 5, 0))) {
+               tevent_req_oom(req);
+               return tevent_req_post(req, ev);
+       }
        tevent_req_set_callback(subreq, g_lock_lock_retry, req);
        return req;
 }
@@ -243,6 +249,18 @@ static void g_lock_lock_retry(struct tevent_req *subreq)
 
        status = dbwrap_record_watch_recv(subreq, talloc_tos(), &rec);
        TALLOC_FREE(subreq);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+               rec = dbwrap_fetch_locked(
+                       state->ctx->db, talloc_tos(),
+                       string_term_tdb_data(state->name));
+               if (rec == NULL) {
+                       status = map_nt_error_from_unix(errno);
+               } else {
+                       status = NT_STATUS_OK;
+               }
+       }
+
        if (tevent_req_nterror(req, status)) {
                return;
        }
@@ -263,6 +281,12 @@ static void g_lock_lock_retry(struct tevent_req *subreq)
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
+       if (!tevent_req_set_endtime(
+                   subreq, state->ev,
+                   timeval_current_ofs(5 + sys_random() % 5, 0))) {
+               tevent_req_oom(req);
+               return;
+       }
        tevent_req_set_callback(subreq, g_lock_lock_retry, req);
        return;