]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Fixup race condition in ub_cancel. For 1.3.0.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 5 Feb 2009 09:48:02 +0000 (09:48 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 5 Feb 2009 09:48:02 +0000 (09:48 +0000)
git-svn-id: file:///svn/unbound/trunk@1451 be551aaa-1e26-0410-a405-d3ace91eadb9

configure
configure.ac
doc/Changelog
doc/libunbound.3.in
libunbound/context.h
libunbound/libunbound.c
libunbound/unbound.h
testcode/asynclook.c

index 0993722d18500fd05d73548dcd7af82efa248f76..fc0a44deff683038ad0a3f98f1f881014899b6a4 100755 (executable)
--- a/configure
+++ b/configure
@@ -1945,7 +1945,7 @@ LIBUNBOUND_AGE=0
 # 1.1.1 had 0:16:0
 # 1.2.0 had 0:17:0
 # 1.2.1 had 0:18:0
-# 1.3.0 had 0:19:0
+# 1.3.0 had 1:0:1
 
 #   Current  -- the number of the binary API that we're implementing
 #   Revision -- which iteration of the implementation of the binary
index 347770f0eedcc6d88b5bff841a1d880859fa17fe..723bfe4fb86c048f8752c2dfb756bfacd9581350 100644 (file)
@@ -14,7 +14,7 @@ LIBUNBOUND_AGE=0
 # 1.1.1 had 0:16:0
 # 1.2.0 had 0:17:0
 # 1.2.1 had 0:18:0
-# 1.3.0 had 0:19:0
+# 1.3.0 had 1:0:1
 
 #   Current  -- the number of the binary API that we're implementing
 #   Revision -- which iteration of the implementation of the binary
index 4943507d5a7b445ad465778b7fa81949bcb0996c..1e12c604424a7a196657f1750a931750e7c5c2ee 100644 (file)
@@ -1,5 +1,12 @@
 5 February 2009: Wouter
        - ldns 1.5.0 rc as tarball included.
+       - 1.3.0 development continues:
+         change in libunbound API: ub_cancel can return an error, that
+         the async_id did not exist, or that it was already delivered.
+         The result could have been delivered just before the cancel 
+         routine managed to acquire the lock, so a caller may get the
+         result at the same time they call cancel.  For this case, 
+         ub_cancel tries to return an error code.
 
 4 February 2009: Wouter
        - tag for release 1.2.1.
index 96fd854b066fb3c5d3ed8b7235e57cdc529f2e47..ad7996ec96197eaa21ca502e24fe11cdb3c7ac0f 100644 (file)
@@ -281,7 +281,8 @@ The async_id is returned so you can (at your option) decide to track it
 and cancel the request if needed.
 .TP
 .B ub_cancel
-Cancel an async query in progress.
+Cancel an async query in progress.  This may return an error if the query
+does not exist, or was already delivered.
 .TP
 .B ub_resolve_free
 Free struct ub_result contents after use.
index e1542a6ea634a12b5f931bf91a01af6dd1d73abc..8898f3ebfdf92d53780a6f2e4e1098d9b737683d 100644 (file)
@@ -184,7 +184,9 @@ enum ub_ctx_err {
        /** error in pipe communication with async bg worker */
        UB_PIPE = -8,
        /** error reading from file (resolv.conf) */
-       UB_READFILE = -9
+       UB_READFILE = -9,
+       /** error async_id does not exist or result already been delivered */
+       UB_NOID = -10
 };
 
 /**
index d646ffee8bd8e60ed9cc0f89277d7b2655a0d1c1..9c5c79fcf71a569ae82ffd159d76a9a67194a2dd 100644 (file)
@@ -642,7 +642,7 @@ ub_cancel(struct ub_ctx* ctx, int async_id)
        if(!q || !q->async) {
                /* it is not there, so nothing to do */
                lock_basic_unlock(&ctx->cfglock);
-               return UB_NOERROR;
+               return UB_NOID;
        }
        log_assert(q->async);
        q->cancelled = 1;
@@ -703,6 +703,7 @@ ub_strerror(int err)
                case UB_AFTERFINAL: return "setting change after finalize";
                case UB_PIPE: return "error in pipe communication with async";
                case UB_READFILE: return "error reading file";
+               case UB_NOID: return "error async_id does not exist";
                default: return "unknown error";
        }
 }
index 8e52e47e8f1fbe91787ef651a91e6ee554e6e969..e9e5f6ebcf80f567dbe6bfe57b10aa2ff5ba488c 100644 (file)
@@ -449,6 +449,11 @@ int ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype,
  * @param ctx: context.
  * @param async_id: which query to cancel.
  * @return 0 if OK, else error.
+ * This routine can return an error if the async_id passed does not exist
+ * or has already been delivered. If another thread is processing results
+ * at the same time, the result may be delivered at the same time and the
+ * cancel fails with an error.  Also the cancel can fail due to a system
+ * error, no memory or socket failures.
  */
 int ub_cancel(struct ub_ctx* ctx, int async_id);
 
index f0ffb808e7f1ba0ff69de8e6a086775472bdecfd..10e34fc1c5aae6ab820750bd10f49a08b1fd632f 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "config.h"
 #include "libunbound/unbound.h"
+#include "libunbound/context.h"
 #include "util/locks.h"
 #include "util/log.h"
 
@@ -301,7 +302,8 @@ ext_thread(void* arg)
                                r = ub_cancel(inf->ctx, async_ids[i-100].id);
                                async_ids[i-100].cancel=1;
                                lock_basic_unlock(&async_ids[i-100].lock);
-                               checkerr("ub_cancel", r);
+                               if(r != UB_NOID) 
+                                       checkerr("ub_cancel", r);
                        }
                } else if(inf->thread_num > NUMTHR/2) {
                        /* async */
@@ -467,7 +469,8 @@ int main(int argc, char** argv)
                for(i=0; i<argc; i++) {
                        fprintf(stderr, "cancel %s\n", argv[i]);
                        r = ub_cancel(ctx, lookups[i].async_id);
-                       checkerr("ub_cancel", r);
+                       if(r != UB_NOID) 
+                               checkerr("ub_cancel", r);
                }
                num_wait = 0;
        }