From f8c1be85d1d80fae4b71634a411ab354756c3bda Mon Sep 17 00:00:00 2001 From: Mikhail Zakharov Date: Wed, 2 Jan 2019 10:05:17 -0500 Subject: [PATCH] unix/mpthreadport: Add thread deinit code to stop threads on exit. Free unused memory for threads and cancel any outstanding threads on interpreter exit to avoid possible segmentaiton fault. --- ports/unix/main.c | 4 ++++ ports/unix/mpthreadport.c | 14 ++++++++++++++ ports/unix/mpthreadport.h | 1 + 3 files changed, 19 insertions(+) diff --git a/ports/unix/main.c b/ports/unix/main.c index 1cf237a2b2..8d455fa834 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -647,6 +647,10 @@ MP_NOINLINE int main_(int argc, char **argv) { } #endif + #if MICROPY_PY_THREAD + mp_thread_deinit(); + #endif + #if defined(MICROPY_UNIX_COVERAGE) gc_sweep_all(); #endif diff --git a/ports/unix/mpthreadport.c b/ports/unix/mpthreadport.c index baca0a2b1e..7170379f4e 100644 --- a/ports/unix/mpthreadport.c +++ b/ports/unix/mpthreadport.c @@ -93,6 +93,19 @@ void mp_thread_init(void) { sigaction(SIGUSR1, &sa, NULL); } +void mp_thread_deinit(void) { + pthread_mutex_lock(&thread_mutex); + while (thread->next != NULL) { + thread_t *th = thread; + thread = thread->next; + pthread_cancel(th->id); + free(th); + } + pthread_mutex_unlock(&thread_mutex); + assert(thread->id == pthread_self()); + free(thread); +} + // This function scans all pointers that are external to the current thread. // It does this by signalling all other threads and getting them to scan their // own registers and stack. Note that there may still be some edge cases left @@ -127,6 +140,7 @@ void mp_thread_set_state(void *state) { } void mp_thread_start(void) { + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_mutex_lock(&thread_mutex); for (thread_t *th = thread; th != NULL; th = th->next) { if (th->id == pthread_self()) { diff --git a/ports/unix/mpthreadport.h b/ports/unix/mpthreadport.h index b158ed5bcc..dfd2975c25 100644 --- a/ports/unix/mpthreadport.h +++ b/ports/unix/mpthreadport.h @@ -29,4 +29,5 @@ typedef pthread_mutex_t mp_thread_mutex_t; void mp_thread_init(void); +void mp_thread_deinit(void); void mp_thread_gc_others(void);