Ticket Hash: | 2c5661c26a0c1b50e083af7110001267b934d912 | ||
Title: | Thread safety: does SQLite handle pthread_cancel cleanly? | ||
Status: | Closed | Type: | Feature_Request |
Severity: | Important | Priority: | Immediate |
Subsystem: | Other | Resolution: | Rejected |
Last Modified: |
2014-03-11 12:56:01 11.28 years ago |
Created: |
2009-08-24 05:53:27 15.82 years ago |
Version Found In: | 3.6.17 |
Description: | ||||
While fixing a threaded server application that uses sqlite3, I've notice that sometimes the application crashes during termination in sqlite functions depending on the timing of thread termination using pthread_cancel(). It is unclear to me whether sqlite takes pthread_cancel into consideration, so I thought to raise this ticket for future consideration, since I myself have been neglect until recently concerning issues with pthread_cancel.
There are issues of concern related to pthread_cancel that I've come across recently: 1. Calling pthread_cancel while a thread has a mutex locked, can cause other threads to deadlock. On OpenBSD (and probably Linux) pthread_cond_wait is a cancellation point, which means: pthread_lock(&mutex) while (condition not true) pthread_cond_wait(&cond_var, &mutex) pthread_unlock(&mutex) Could result in the thread terminating while blocked on a conditional variable with mutex locked. I've found the following idiom useful: pthread_mutex_lock(&mutex) pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &mutex) while (condition not true) pthread_cond_wait(&cond_var, &mutex) pthread_cleanup_pop(1) in order to guarantee that the mutex is released when the thread terminates due to pthread_cancel. The use of pthread_cleanup_push / pop should probably be used any place that mutex lock/unlock protects a complex region of code, not just the case of conditional variables. OpenBSD documents their cancellation points, while Linux does not. From OpenBSD 4.0 man pthread_testcancel Cancellation Points Cancellation points will occur when a thread is executing the following functions: close(), creat(), fcntl(), fsync(), msync(), nanosleep(), open(), pause(), pthread_cond_timedwait(), pthread_cond_wait(), pthread_join(), pthread_testcancel(), read(), sigwaitinfo(), sigsuspend(), sigwait(), sleep(), system(), tcdrain(), wait(), waitpid(), write(). 2. Calling pthread_cancel while a thread is performing critical functions. If pthread_cleanup_push/pop are not suitable, then consider deferring thread cancellation around complex sections of code: int old_state; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state); ...long complex series of operations, like file IO... pthread_setcancelstate(old_state, NULL); I've found in my own code, in order to avoid potential problems related to pthread_cancel, that wrapping calls to sqlite3_exec, sqlite3_step, sqlite3_close appears to reduce, if not eliminate potential crashes and/or corruption. 3. Another possible issue of concern pthread_setcanceltype, similar to pthread_setcancelstate, which can be set to deferred or asynchronous by the calling application. Library functions that temporarily disable cancellation probably need not worry. I raise the point only for consideration. |