summaryrefslogtreecommitdiff
path: root/src/irmd/reg_api.c
diff options
context:
space:
mode:
authordimitri staessens <[email protected]>2016-08-10 12:28:02 +0200
committerdimitri staessens <[email protected]>2016-08-10 13:03:15 +0200
commitaca897331ff55c80d926b0bdb90f1c8962bf7a6e (patch)
treec71b8d8c6b35ad012f4a8bb673749275fa3806bf /src/irmd/reg_api.c
parent27c99995c8059eb897b704d84596ca0abca6db9b (diff)
downloadouroboros-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.c59
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);
}