aboutsummaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorMatias Elo <matias.elo@nokia.com>2023-05-08 09:24:48 +0300
committerMatias Elo <matias.elo@nokia.com>2023-05-09 10:17:39 +0300
commitd16710c38e3f0e91ee0a6cd8f5e1fc7d1ab6d9ae (patch)
tree97173301e47c4e49791d53396ab40b3a275e8e29 /platform
parent13918e69c848509cd8b75eb069ec53e4f8f24f74 (diff)
linux-gen: timer: fix global term crash
Avoid crash in odp_term_global() if a timer pool has not been properly destroyed when using posix timer based implementation. Signed-off-by: Matias Elo <matias.elo@nokia.com> Reviewed-by: Petri Savolainen <petri.savolainen@nokia.com>
Diffstat (limited to 'platform')
-rw-r--r--platform/linux-generic/odp_timer.c52
1 files changed, 35 insertions, 17 deletions
diff --git a/platform/linux-generic/odp_timer.c b/platform/linux-generic/odp_timer.c
index b2ed7f102..b2c045213 100644
--- a/platform/linux-generic/odp_timer.c
+++ b/platform/linux-generic/odp_timer.c
@@ -320,6 +320,22 @@ static void block_sigalarm(void)
sigprocmask(SIG_BLOCK, &sigset, NULL);
}
+static void posix_timer_stop(timer_pool_t *tp)
+{
+ int ret;
+
+ /* Stop POSIX timer signals */
+ if (timer_delete(tp->timerid) != 0)
+ _ODP_ABORT("timer_delete() returned error: %s\n", strerror(errno));
+
+ /* Stop the thread */
+ _ODP_DBG("stop\n");
+ tp->thr_exit = 1;
+ ret = pthread_join(tp->thr_pthread, NULL);
+ if (ret != 0)
+ _ODP_ABORT("Unable to join thread, err %d\n", ret);
+}
+
static void odp_timer_pool_del(timer_pool_t *tp)
{
int highest;
@@ -327,20 +343,8 @@ static void odp_timer_pool_del(timer_pool_t *tp)
odp_spinlock_lock(&tp->lock);
- if (!odp_global_rw->inline_timers) {
- int ret;
-
- /* Stop POSIX timer signals */
- if (timer_delete(tp->timerid) != 0)
- _ODP_ABORT("timer_delete() returned error %s\n", strerror(errno));
-
- /* Stop the thread */
- _ODP_DBG("stop\n");
- tp->thr_exit = 1;
- ret = pthread_join(tp->thr_pthread, NULL);
- if (ret != 0)
- _ODP_ABORT("unable to join thread, err %d\n", ret);
- }
+ if (!odp_global_rw->inline_timers)
+ posix_timer_stop(tp);
if (tp->num_alloc != 0) {
/* It's a programming error to attempt to destroy a */
@@ -2005,16 +2009,30 @@ int _odp_timer_term_global(void)
{
odp_shm_t shm;
int i;
+ int rc = 0;
if (timer_global == NULL)
return 0;
for (i = 0; i < MAX_TIMER_POOLS; i++) {
shm = timer_global->tp_shm[i];
+
+ if (timer_global->timer_pool_used[i]) {
+ _ODP_ERR("Not destroyed timer pool: %i\n", i);
+ rc = -1;
+
+ /* Prevent crash from timer thread */
+ if (!odp_global_rw->inline_timers) {
+ timer_pool_t *tp = timer_global->timer_pool[i];
+
+ if (tp != NULL)
+ posix_timer_stop(tp);
+ }
+ }
if (shm != ODP_SHM_INVALID) {
if (odp_shm_free(shm)) {
- _ODP_ERR("Shm free failed for timer pool %i\n", i);
- return -1;
+ _ODP_ERR("Shm free failed for timer pool: %i\n", i);
+ rc = -1;
}
}
}
@@ -2024,7 +2042,7 @@ int _odp_timer_term_global(void)
return -1;
}
- return 0;
+ return rc;
}
int _odp_timer_init_local(void)