summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/cache.c14
-rw-r--r--lib/error.c1
-rw-r--r--lib/nl.c18
3 files changed, 30 insertions, 3 deletions
diff --git a/lib/cache.c b/lib/cache.c
index 7afa42e..3b453a9 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -677,6 +677,7 @@ int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache,
NL_DBG(1, "Resyncing cache %p <%s>...\n", cache, nl_cache_name(cache));
+restart:
/* Mark all objects so we can see if some of them are obsolete */
nl_cache_mark_all(cache);
@@ -685,7 +686,9 @@ int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache,
goto errout;
err = __cache_pickup(sk, cache, &p);
- if (err < 0)
+ if (err == -NLE_DUMP_INTR)
+ goto restart;
+ else if (err < 0)
goto errout;
nl_list_for_each_entry_safe(obj, next, &cache->c_items, ce_list) {
@@ -770,6 +773,7 @@ int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache)
{
int err;
+restart:
err = nl_cache_request_full_dump(sk, cache);
if (err < 0)
return err;
@@ -778,7 +782,13 @@ int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache)
cache, nl_cache_name(cache));
nl_cache_clear(cache);
- return nl_cache_pickup(sk, cache);
+ err = nl_cache_pickup(sk, cache);
+ if (err == -NLE_DUMP_INTR) {
+ fprintf(stderr, "dump interrupted, restarting!\n");
+ goto restart;
+ }
+
+ return err;
}
/** @} */
diff --git a/lib/error.c b/lib/error.c
index 8934020..e8ee474 100644
--- a/lib/error.c
+++ b/lib/error.c
@@ -46,6 +46,7 @@ static const char *errmsg[NLE_MAX+1] = {
[NLE_PARSE_ERR] = "Unable to parse object",
[NLE_NODEV] = "No such device",
[NLE_IMMUTABLE] = "Immutable attribute",
+[NLE_DUMP_INTR] = "Dump inconsistency detected, interrupted",
};
/**
diff --git a/lib/nl.c b/lib/nl.c
index fc70374..cc450c7 100644
--- a/lib/nl.c
+++ b/lib/nl.c
@@ -559,7 +559,7 @@ do { \
static int recvmsgs(struct nl_sock *sk, struct nl_cb *cb)
{
- int n, err = 0, multipart = 0;
+ int n, err = 0, multipart = 0, interrupted = 0;
unsigned char *buf = NULL;
struct nlmsghdr *hdr;
struct sockaddr_nl nla = {0};
@@ -631,6 +631,19 @@ continue_reading:
if (hdr->nlmsg_flags & NLM_F_MULTI)
multipart = 1;
+
+ if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) {
+ if (cb->cb_set[NL_CB_DUMP_INTR])
+ NL_CB_CALL(cb, NL_CB_DUMP_INTR, msg);
+ else {
+ /*
+ * We have to continue reading to clear
+ * all messages until a NLMSG_DONE is
+ * received and report the inconsistency.
+ */
+ interrupted = 1;
+ }
+ }
/* Other side wishes to see an ack for this message */
if (hdr->nlmsg_flags & NLM_F_ACK) {
@@ -738,6 +751,9 @@ out:
free(buf);
free(creds);
+ if (interrupted)
+ err = -NLE_DUMP_INTR;
+
return err;
}