backends: delay `cleanup()` until `setup()` or `dispatch()` finishes
authorPavel Šimerda <psimerda@redhat.com>
Fri, 7 Nov 2014 20:06:41 +0000 (21:06 +0100)
committerPavel Šimerda <psimerda@redhat.com>
Fri, 7 Nov 2014 20:49:14 +0000 (21:49 +0100)
This change effectively removes an unwritten requirement for reentrancy
of the backend, i.e. the requirement to call netresolve backend API
functions always at the and as they could do just anything.

The backend can now safely assume that none of its functions will be
triggered by the backend API functions. In other words, calls to
functions of a single backend are serialized.

README
include/netresolve-private.h
lib/backend.c
lib/query.c

diff --git a/README b/README
index 7a33cd3165ca7e9a4987549173903bd547d2de0b..0f5bde7bcdd7665ec766ba1d9372898e0261c11c 100644 (file)
--- a/README
+++ b/README
@@ -313,6 +313,8 @@ When success or failure was reported by the plugin, or when the query has been c
 
 The cleanup function also retrieves the state object, removes remaining watchers using `netresolve_backend_watch_fd()` and/or `netresolve_backend_remove_timeout()`, closes open file descriptors, returns allocated memory (except the context object itself which is freed by netresolve itself).
 
+Calls to the above functions in a single backend are serialized, calling a backend API function doesn't cause any side effects for the backend.
+
 ## Known bugs
 
 The library doesn't currently sort paths according to their priority and/or RFC rules. The c-ares library blocks when /etc/resolv.conf is empty instead of quitting immediately, which in turn breaks tests when offline. The DNS backend doesn't support search domains. For more information, see the `TODO` file. 
index b40c0b69b8792a886fcc25d57101ef17d46e0c5d..ee5573108294d350d39ecedb5df3deabf40dbb09 100644 (file)
@@ -54,6 +54,7 @@ enum netresolve_state {
        NETRESOLVE_STATE_RESOLVED,
        NETRESOLVE_STATE_CONNECTING,
        NETRESOLVE_STATE_DONE,
+       NETRESOLVE_STATE_ERROR,
        NETRESOLVE_STATE_FAILED
 };
 
index a42993f85a97eb37eef7a98021c4c256907be309..df879b1f53c4ca176bc7e03f3dbf2da0d8d955a1 100644 (file)
@@ -312,7 +312,7 @@ netresolve_backend_finished(netresolve_query_t query)
 void
 netresolve_backend_failed(netresolve_query_t query)
 {
-       netresolve_query_set_state(query, NETRESOLVE_STATE_FAILED);
+       netresolve_query_set_state(query, NETRESOLVE_STATE_ERROR);
 }
 
 bool
index b6f72d983105eec965d0233e7ee2797da1c95cd9..e45f9d88369538d178056bb9dfc3a64be5d221b2 100644 (file)
@@ -51,6 +51,8 @@ state_to_string(enum netresolve_state state)
                return "connecting";
        case NETRESOLVE_STATE_DONE:
                return "done";
+       case NETRESOLVE_STATE_ERROR:
+               return "error";
        case NETRESOLVE_STATE_FAILED:
                return "failed";
        }
@@ -115,6 +117,8 @@ netresolve_query_set_state(netresolve_query_t query, enum netresolve_state state
                                setup(query, backend->settings + 1);
                                if (query->state == NETRESOLVE_STATE_SETUP)
                                        netresolve_query_set_state(query, NETRESOLVE_STATE_WAITING);
+                               if (query->state == NETRESOLVE_STATE_ERROR)
+                                       netresolve_query_set_state(query, NETRESOLVE_STATE_FAILED);
                        } else
                                netresolve_query_set_state(query, NETRESOLVE_STATE_FAILED);
                }
@@ -130,8 +134,7 @@ netresolve_query_set_state(netresolve_query_t query, enum netresolve_state state
                                abort();
                        }
                        netresolve_watch_fd(query->channel, query->delayed_fd, POLLIN);
-               } else
-                       netresolve_query_set_state(query, NETRESOLVE_STATE_CONNECTING);
+               }
                break;
        case NETRESOLVE_STATE_CONNECTING:
                cleanup_query(query);
@@ -157,6 +160,8 @@ netresolve_query_set_state(netresolve_query_t query, enum netresolve_state state
                if (query->channel->callbacks.on_success)
                        query->channel->callbacks.on_success(query, query->channel->callbacks.user_data);
                break;
+       case NETRESOLVE_STATE_ERROR:
+               break;
        case NETRESOLVE_STATE_FAILED:
                if (query->response.pathcount)
                        error("Failed reply has data.");
@@ -241,7 +246,15 @@ netresolve_query_dispatch(netresolve_query_t query, int fd, int events)
        switch (query->state) {
        case NETRESOLVE_STATE_WAITING_MORE:
        case NETRESOLVE_STATE_WAITING:
-               return backend && backend->dispatch && (backend->dispatch(query, fd, events), true);
+               if (backend && backend->dispatch) {
+                       backend->dispatch(query, fd, events);
+                       if (query->state == NETRESOLVE_STATE_RESOLVED)
+                               netresolve_query_set_state(query, NETRESOLVE_STATE_CONNECTING);
+                       if (query->state == NETRESOLVE_STATE_ERROR)
+                               netresolve_query_set_state(query, NETRESOLVE_STATE_FAILED);
+                       return true;
+               }
+               return false;
        case NETRESOLVE_STATE_RESOLVED:
                return dispatch_timeout(query, &query->delayed_fd, NETRESOLVE_STATE_CONNECTING, fd, events);
        case NETRESOLVE_STATE_CONNECTING:
This page took 0.072352 seconds and 5 git commands to generate.