diff options
author | Chris Hall <chris.hall@highwayman.com> | 2012-06-08 15:01:11 +0100 |
---|---|---|
committer | Chris Hall <chris.hall@highwayman.com> | 2012-06-08 15:01:11 +0100 |
commit | 58b4a3411f12d3ef34ef52ab197729887074f321 (patch) | |
tree | e456eec427d977e2e723039b83d614d13edcf983 /lib/list_util.h | |
parent | 12d01b8b9c68f5dc72f2accdb29a760feb31420a (diff) | |
download | quagga-ex25b.tar.bz2 quagga-ex25b.tar.xz |
Fix bugs in vty error handlingex25b
Advance version to 0.99.20ex25b.
Bug fixes:
* when closing a vty, if close() returned an error, the vtys would
fall into a loop trying to recover.
This was found on FreeBSD, which will return ECONNRESET on close(),
which is not standard POSIX behaviour.
* when closing a vty in response to EPIPE or ECONNRESET, managed to
leave the vty mutex locked.
This stopped the Routing Engine *dead* on the next CLI command
that required the Routing Engine. SIGTERM/SIGINT would not
stop bgpd -- a SIGKILL would be required.
Other changes:
* toned down the error reporting of EPIPE in the vty -- so no
longer looks like an error...
...closing a vty by "exit" command is logged as "closed"
...closing a vty in response to the client closing their end of
the connection is logged as "terminated: terminal closed",
and no longer logs an EPIPE error.
* changed error reporting on close() and shutdown() for vty, so
that nothing is logged if an i/o error has already logged...
...so that redundant error messages are suppressed.
* applied slightly finer jittering to bgpd timers.
* work in progress on new vtysh.
Diffstat (limited to 'lib/list_util.h')
-rw-r--r-- | lib/list_util.h | 140 |
1 files changed, 125 insertions, 15 deletions
diff --git a/lib/list_util.h b/lib/list_util.h index 19183760..23677cd5 100644 --- a/lib/list_util.h +++ b/lib/list_util.h @@ -512,14 +512,18 @@ Private bool ssl_del_func(void** p_prev, void* item, size_t link_offset) * * ddl_in_after(after, base, item, list) -- insert after * - * Treat as void function. The after & item may *not* be NULL. + * Treat as void function. The item may *not* be NULL. + * + * If after == NULL, insert item at the end of the current list. * * Undefined if item is already on any list (including this one), or if * after is not on the list. * * ddl_in_before(before, base, item, list) -- insert before * - * Treat as void function. The before & item may *not* be NULL. + * Treat as void function. The item may *not* be NULL. + * + * If before == NULL, insert item at the start of the current list. * * Undefined if item is already on any list (including this one), or if * before is not on the list. @@ -570,6 +574,24 @@ Private bool ssl_del_func(void** p_prev, void* item, size_t link_offset) * * Treat as function returning void*. Returns NULL if the item is NULL. * + * ddl_slice(base, sub, list) -- remove sublist from given list + * + * Treat as void function. Does nothing if the sublist is empty. + * + * ddl_splice_after(after, base, sub, list) + * -- insert sublist after given item + * + * Treat as void function. Does nothing if the sublist is empty. + * + * If after == NULL, insert sublist at the end of the current list. + * + * ddl_splice_before(before, base, sub, list) + * -- insert sublist before given item + * + * Treat as void function. Does nothing if the sublist is empty. + * + * If before == NULL, insert sublist at the start of the current list. + * * Note that ddl_del() and ddl_pop() do NOT affect the item->list.next * or item->list.prev pointers. * @@ -577,7 +599,7 @@ Private bool ssl_del_func(void** p_prev, void* item, size_t link_offset) * * "base" to be an r-value of type: struct base_pair(struct item*)* * - * That is... a variable or field which is a pointer to + * That is... a variable or field which is a pointer pair. * * "item" to be an l-value of type struct item* * @@ -586,7 +608,9 @@ Private bool ssl_del_func(void** p_prev, void* item, size_t link_offset) * "list" to be the name of a field in struct item * of type: struct list_pair(struct item*) * + * "sub" to be an r-value of type: struct base_pair(struct item*)* * + * That is... a variable or field which is a pointer pointer pair. * *------------------------------------------------------------------------------ * For example: @@ -672,23 +696,33 @@ Private bool ssl_del_func(void** p_prev, void* item, size_t link_offset) } while (0) #define ddl_in_after(after, base, item, list) \ - do { (item)->list.next = (after)->list.next ; \ - (item)->list.prev = (after) ; \ - if ((after)->list.next != NULL) \ - (after)->list.next->list.prev = (item) ; \ + do { if (after != NULL) \ + { \ + (item)->list.next = (after)->list.next ; \ + (item)->list.prev = (after) ; \ + if ((after)->list.next != NULL) \ + (after)->list.next->list.prev = (item) ; \ + else \ + (base).tail = (item) ; \ + (after)->list.next = (item) ; \ + } \ else \ - (base).tail = (item) ; \ - (after)->list.next = (item) ; \ + ddl_append(base, item, list) ; \ } while (0) #define ddl_in_before(before, base, item, list) \ - do { (item)->list.next = (before) ; \ - (item)->list.prev = (before)->list.prev ; \ - if ((before)->list.prev != NULL) \ - (before)->list.prev->list.next = (item) ; \ + do { if (before != NULL) \ + { \ + (item)->list.next = (before) ; \ + (item)->list.prev = (before)->list.prev ; \ + if ((before)->list.prev != NULL) \ + (before)->list.prev->list.next = (item) ; \ + else \ + (base).head = (item) ; \ + (before)->list.prev = (item) ; \ + } \ else \ - (base).head = (item) ; \ - (before)->list.prev = (item) ; \ + ddl_push(base, item, list) ; \ } while (0) #define ddl_del(base, item, list) \ @@ -751,6 +785,82 @@ Private bool ssl_del_func(void** p_prev, void* item, size_t link_offset) #define ddl_prev(item, list) \ ((item) != NULL ? (item)->list.prev : NULL) +#define ddl_slice(base, sub, list) \ + do { if ((sub).head != NULL) \ + { \ + if ((sub).head->list.prev != NULL) \ + (sub).head->list.prev->list.next = (sub).tail->list.next ; \ + else \ + { \ + qassert((sub).head == (base).head) ; \ + (base).head = (sub).tail->list.next ; \ + } ; \ + \ + if ((sub).tail->list.next != NULL) \ + (sub).tail->list.next->list.prev = (sub).head->list.prev ; \ + else \ + { \ + qassert((sub).tail == (base).tail) ; \ + (base).tail = (sub).head->list.prev ; \ + } ; \ + \ + (sub).head->list.prev = NULL ; \ + (sub).tail->list.next = NULL ; \ + } \ + } while (0) + +#define ddl_splice_after(after, base, sub, list) \ + do { if ((sub).head != NULL) \ + { \ + if (after != NULL) \ + { \ + (sub).head->list.prev = (after) ; \ + (sub).tail->list.next = (after)->list.next ; \ + if ((after)->list.next != NULL) \ + (after)->list.next->list.prev = (sub).tail ; \ + else \ + (base).tail = (sub).tail ; \ + (after)->list.next = (sub).head ; \ + } \ + else \ + { \ + (sub).head->list.prev = (base).tail ; \ + (sub).tail->list.next = NULL ; \ + if ((base).tail != NULL) \ + (base).tail->list.next = (sub).head ; \ + else \ + (base).head = (sub).head ; \ + (base).tail = (sub).tail ; \ + } ; \ + } \ + } while (0) + +#define ddl_splice_before(before, base, sub, list) \ + do { if ((sub).head != NULL) \ + { \ + if (before != NULL) \ + { \ + (sub).tail->list.next = (before) ; \ + (sub).head->list.prev = (before)->list.prev ; \ + if ((before)->list.prev != NULL) \ + (before)->list.prev->list.next = (sub).head ; \ + else \ + (base).head = (sub).head ; \ + (before)->list.prev = (sub).tail ; \ + } \ + else \ + { \ + (sub).tail->list.next = (base).head ; \ + (sub).head->list.prev = NULL ; \ + if ((base).head != NULL) \ + (base).head->list.prev = (sub).tail ; \ + else \ + (base).tail = (sub).tail ; \ + (base).head = (sub).head ; \ + } ; \ + } \ + } while (0) + /*============================================================================== * Double Base, Single Link * |