diff options
author | dimitri staessens <[email protected]> | 2016-08-10 12:28:02 +0200 |
---|---|---|
committer | dimitri staessens <[email protected]> | 2016-08-10 13:03:15 +0200 |
commit | aca897331ff55c80d926b0bdb90f1c8962bf7a6e (patch) | |
tree | c71b8d8c6b35ad012f4a8bb673749275fa3806bf /src/irmd/reg_api.c | |
parent | 27c99995c8059eb897b704d84596ca0abca6db9b (diff) | |
download | ouroboros-aca897331ff55c80d926b0bdb90f1c8962bf7a6e.tar.gz ouroboros-aca897331ff55c80d926b0bdb90f1c8962bf7a6e.zip |
irmd: Graceful shutdown
Threads from the threadpool will now check the state of the IRMd and
exit gracefully without a need to cancel them. This avoids the unsafe
call of pthread_cancel in the signal handler.
Diffstat (limited to 'src/irmd/reg_api.c')
-rw-r--r-- | src/irmd/reg_api.c | 59 |
1 files changed, 37 insertions, 22 deletions
diff --git a/src/irmd/reg_api.c b/src/irmd/reg_api.c index 648dc1b3..5b7750f7 100644 --- a/src/irmd/reg_api.c +++ b/src/irmd/reg_api.c @@ -21,10 +21,15 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <ouroboros/config.h> +#include <ouroboros/time_utils.h> +#include <ouroboros/errno.h> + #include "reg_api.h" #include <stdlib.h> #include <stdbool.h> +#include <time.h> struct reg_api * reg_api_create(pid_t api) { @@ -51,18 +56,18 @@ void reg_api_destroy(struct reg_api * i) pthread_mutex_lock(&i->state_lock); + if (i->state == REG_I_INIT) + i->state = REG_I_NULL; + if (i->state != REG_I_NULL) i->state = REG_I_DESTROY; pthread_cond_signal(&i->state_cond); - pthread_cleanup_push((void(*)(void *)) pthread_mutex_unlock, - (void *) &i->state_lock); - while (i->state != REG_I_NULL) pthread_cond_wait(&i->state_cond, &i->state_lock); - pthread_cleanup_pop(true); + pthread_mutex_unlock(&i->state_lock); pthread_cond_destroy(&i->state_cond); pthread_mutex_destroy(&i->state_lock); @@ -70,32 +75,45 @@ void reg_api_destroy(struct reg_api * i) free(i); } -static void cleanup_sleeper(void * o) { - struct reg_api * i = (struct reg_api *) o; - i->state = REG_I_NULL; - pthread_cond_broadcast(&i->state_cond); - pthread_mutex_unlock(&i->state_lock); -} - -void reg_api_sleep(struct reg_api * i) +int reg_api_sleep(struct reg_api * i) { + struct timespec timeout = {(IRMD_ACCEPT_TIMEOUT / 1000), + (IRMD_ACCEPT_TIMEOUT % 1000) * MILLION}; + struct timespec now; + struct timespec dl; + + int ret = 0; + if (i == NULL) - return; + return -EINVAL; + + clock_gettime(CLOCK_REALTIME, &now); + + ts_add(&now, &timeout, &dl); pthread_mutex_lock(&i->state_lock); if (i->state != REG_I_INIT) { pthread_mutex_unlock(&i->state_lock); - return; + return -EINVAL; } i->state = REG_I_SLEEP; - pthread_cleanup_push(cleanup_sleeper, (void *) i); + while (i->state == REG_I_SLEEP) { + if ((ret = -pthread_cond_timedwait(&i->state_cond, + &i->state_lock, + &dl)) == -ETIMEDOUT) { + i->state = REG_I_INIT; + break; + } else { + i->state = REG_I_NULL; + pthread_cond_broadcast(&i->state_cond); + } + } - while (i->state == REG_I_SLEEP) - pthread_cond_wait(&i->state_cond, &i->state_lock); + pthread_mutex_unlock(&i->state_lock); - pthread_cleanup_pop(true); + return ret; } void reg_api_wake(struct reg_api * i) @@ -111,11 +129,8 @@ void reg_api_wake(struct reg_api * i) pthread_cond_broadcast(&i->state_cond); - pthread_cleanup_push((void(*)(void *)) pthread_mutex_unlock, - (void *) &i->state_lock); - while (i->state == REG_I_WAKE) pthread_cond_wait(&i->state_cond, &i->state_lock); - pthread_cleanup_pop(true); + pthread_mutex_unlock(&i->state_lock); } |