From c433326c9f17b0b623aaced6688104758bc61b54 Mon Sep 17 00:00:00 2001 From: PartialVolume Date: Tue, 7 Dec 2021 23:10:20 +0000 Subject: [PATCH] Improve thread cancellation error reporting Check for specific errors. Add retry loop with timeout for pthread_join. --- src/nwipe.c | 78 +++++++++++++++++++++++++++++++++++++++++---------- src/nwipe.h | 9 ++---- src/version.c | 4 +-- 3 files changed, 67 insertions(+), 24 deletions(-) diff --git a/src/nwipe.c b/src/nwipe.c index 12392a26..ae13e257 100644 --- a/src/nwipe.c +++ b/src/nwipe.c @@ -61,6 +61,8 @@ int main( int argc, char** argv ) int nwipe_enumerated; // The number of contexts that have been enumerated. int nwipe_error = 0; // An error counter. int nwipe_selected = 0; // The number of contexts that have been selected. + int any_threads_still_running; // used in wipe thread cancellation wait loop + int thread_timeout_counter; // timeout thread cancellation after THREAD_CANCELLATION_TIMEOUT seconds pthread_t nwipe_gui_thread = 0; // The thread ID of the GUI thread. pthread_t nwipe_sigint_thread; // The thread ID of the sigint handler. @@ -587,7 +589,6 @@ int main( int argc, char** argv ) if( nwipe_options.verbose ) { nwipe_log( NWIPE_LOG_INFO, "Requesting wipe thread cancellation for %s", c2[i]->device_name ); - nwipe_log( NWIPE_LOG_INFO, "Please wait.." ); } pthread_cancel( c2[i]->thread ); } @@ -622,27 +623,74 @@ int main( int argc, char** argv ) } /* Now join the wipe threads and wait until they have terminated */ - for( i = 0; i < nwipe_selected; i++ ) + any_threads_still_running = 1; + thread_timeout_counter = THREAD_CANCELLATION_TIMEOUT; + while( any_threads_still_running ) { + /* quit waiting if we've tried 'thread_timeout_counter' times */ + if( thread_timeout_counter == 0 ) + { + break; + } - if( c2[i]->thread ) + any_threads_still_running = 0; + for( i = 0; i < nwipe_selected; i++ ) { - /* Joins the thread and waits for completion before continuing */ - r = pthread_join( c2[i]->thread, NULL ); - if( r != 0 ) + if( c2[i]->thread ) { - nwipe_log( NWIPE_LOG_WARNING, "main()>pthread_join():Error when waiting for wipe thread to cancel." ); - } - c2[i]->thread = 0; /* Zero the thread so we know it's been cancelled */ + printf( "\nWaiting for wipe thread to cancel for %s\n", c2[i]->device_name ); - if( nwipe_options.verbose ) - { - nwipe_log( NWIPE_LOG_INFO, "Wipe thread for device %s has been cancelled", c2[i]->device_name ); - } + /* Joins the thread and waits for completion before continuing */ + r = pthread_join( c2[i]->thread, NULL ); + if( r != 0 ) + { + nwipe_log( NWIPE_LOG_ERROR, + "Error joining the wipe thread when waiting for thread to cancel.", + c2[i]->device_name ); + + if( r == EDEADLK ) + { + nwipe_log( NWIPE_LOG_ERROR, + "Error joining the wipe thread: EDEADLK: Deadlock detected.", + c2[i]->device_name ); + } + else + { + if( r == EINVAL ) + { + nwipe_log( NWIPE_LOG_ERROR, + "Error joining the wipe thread: %s EINVAL: thread is not joinable.", + c2[i]->device_name ); + } + else + { + if( r == ESRCH ) + { + nwipe_log( NWIPE_LOG_ERROR, + "Error joining the wipe thread: %s ESRCH: no matching thread found", + c2[i]->device_name ); + } + } + } - /* Close the device file descriptor. */ - close( c2[i]->device_fd ); + any_threads_still_running = 1; + } + else + { + c2[i]->thread = 0; /* Zero the thread so we know it's been cancelled */ + + if( nwipe_options.verbose ) + { + nwipe_log( NWIPE_LOG_INFO, "Wipe thread for device %s has terminated", c2[i]->device_name ); + } + + /* Close the device file descriptor. */ + close( c2[i]->device_fd ); + } + } } + thread_timeout_counter--; + sleep( 1 ); } if( nwipe_options.verbose ) { diff --git a/src/nwipe.h b/src/nwipe.h index adb434d0..73f6f991 100644 --- a/src/nwipe.h +++ b/src/nwipe.h @@ -76,13 +76,6 @@ extern int errno; /* 0=wipe not yet started, 1=wipe has been started by the user */ extern int global_wipe_status; -/* Global array to hold log values to print when logging to STDOUT */ -/* char **log_lines; -int log_current_element = 0; -int log_elements_allocated = 0; -int log_elements_displayed = 0; -pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; */ - /* Ncurses headers. */ #ifdef NCURSES_IN_SUBDIR #include @@ -113,6 +106,8 @@ typedef unsigned char u8; #define BLKBSZSET _IOW( 0x12, 113, size_t ) #define BLKGETSIZE64 _IOR( 0x12, 114, sizeof( u64 ) ) +#define THREAD_CANCELLATION_TIMEOUT 10 + /* This is required for ioctl FDFLUSH. */ #include diff --git a/src/version.c b/src/version.c index 9b146580..0a825004 100644 --- a/src/version.c +++ b/src/version.c @@ -4,7 +4,7 @@ * used by configure to dynamically assign those values * to documentation files. */ -const char* version_string = "0.32.016"; +const char* version_string = "0.32.017"; const char* program_name = "nwipe"; const char* author_name = "Martijn van Brummelen"; const char* email_address = "git@brumit.nl"; @@ -14,4 +14,4 @@ Modifications to original dwipe Copyright Andy Beverley \n\ This is free software; see the source for copying conditions.\n\ There is NO warranty; not even for MERCHANTABILITY or FITNESS\n\ FOR A PARTICULAR PURPOSE.\n"; -const char* banner = "nwipe 0.32.016"; +const char* banner = "nwipe 0.32.017";