diff --git a/main/db.c b/main/db.c index eff8d44c1ef6dc70254d4c83938d41875a1a0b00..f6ad411e5cc4957f364af5a0cfc1910c630379f0 100644 --- a/main/db.c +++ b/main/db.c @@ -112,6 +112,7 @@ static ast_cond_t dbcond; static sqlite3 *astdb; static pthread_t syncthread; static int doexit; +static int dosync; static void db_sync(void); @@ -939,6 +940,7 @@ static int manager_dbdeltree(struct mansession *s, const struct message *m) */ static void db_sync(void) { + dosync = 1; ast_cond_signal(&dbcond); } @@ -957,6 +959,14 @@ static void *db_sync_thread(void *data) ast_mutex_lock(&dblock); ast_db_begin_transaction(); for (;;) { + /* If dosync is set, db_sync() was called during sleep(1), + * and the pending transaction should be committed. + * Otherwise, block until db_sync() is called. + */ + while (!dosync) { + ast_cond_wait(&dbcond, &dblock); + } + dosync = 0; /* We're ok with spurious wakeups, so we don't worry about a predicate */ ast_cond_wait(&dbcond, &dblock); if (ast_db_commit_transaction()) { @@ -970,15 +980,6 @@ static void *db_sync_thread(void *data) ast_mutex_unlock(&dblock); sleep(1); ast_mutex_lock(&dblock); - /* Unfortunately, it is possible for signaling to happen - * when we're not waiting: in the bit when we're unlocked - * above. Do the do-exit check here again. (We could do - * it once, but that would impose a forced delay of 1 - * second always.) */ - if (doexit) { - ast_mutex_unlock(&dblock); - break; - } } return NULL; @@ -995,8 +996,8 @@ static void astdb_atexit(void) /* Set doexit to 1 to kill thread. db_sync must be called with * mutex held. */ - doexit = 1; ast_mutex_lock(&dblock); + doexit = 1; db_sync(); ast_mutex_unlock(&dblock);