mirror of
https://github.com/deltachat/deltachat-core.git
synced 2025-10-05 10:39:27 +02:00
protect against race-condition when interupt() is called while perform-jobs() is running
This commit is contained in:
parent
bd33e707b8
commit
c1108adc33
3 changed files with 53 additions and 12 deletions
55
src/mrjob.c
55
src/mrjob.c
|
@ -680,6 +680,10 @@ void mrmailbox_perform_jobs(mrmailbox_t* mailbox)
|
|||
{
|
||||
mrmailbox_log_info(mailbox, 0, ">>>>> IMAP-jobs started.");
|
||||
|
||||
pthread_mutex_lock(&mailbox->m_imapidle_condmutex);
|
||||
mailbox->m_perform_imap_jobs_needed = 0;
|
||||
pthread_mutex_unlock(&mailbox->m_imapidle_condmutex);
|
||||
|
||||
mrjob_perform(mailbox, MR_IMAP_THREAD);
|
||||
|
||||
mrmailbox_log_info(mailbox, 0, "<<<<< IMAP-jobs ended.");
|
||||
|
@ -723,6 +727,14 @@ void mrmailbox_idle(mrmailbox_t* mailbox)
|
|||
// no return!
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mailbox->m_imapidle_condmutex);
|
||||
if( mailbox->m_perform_imap_jobs_needed ) {
|
||||
mrmailbox_log_info(mailbox, 0, "IMAP-IDLE skipped.");
|
||||
pthread_mutex_unlock(&mailbox->m_imapidle_condmutex);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_unlock(&mailbox->m_imapidle_condmutex);
|
||||
|
||||
mrmailbox_log_info(mailbox, 0, ">>>>> IMAP-IDLE started.");
|
||||
|
||||
mrimap_watch_n_wait(mailbox->m_imap);
|
||||
|
@ -747,6 +759,13 @@ void mrmailbox_interrupt_idle(mrmailbox_t* mailbox)
|
|||
|
||||
mrmailbox_log_info(mailbox, 0, "> > > interrupt IMAP-IDLE.");
|
||||
|
||||
pthread_mutex_lock(&mailbox->m_imapidle_condmutex);
|
||||
// when this function is called, it might be that the idle-thread is in
|
||||
// perform_idle_jobs() instead of idle(). if so, added jobs will be performed after the _next_ idle-jobs loop.
|
||||
// setting the flag perform_imap_jobs_needed makes sure, idle() returns immediately in this case.
|
||||
mailbox->m_perform_imap_jobs_needed = 1;
|
||||
pthread_mutex_unlock(&mailbox->m_imapidle_condmutex);
|
||||
|
||||
mrimap_interrupt_watch(mailbox->m_imap);
|
||||
}
|
||||
|
||||
|
@ -760,6 +779,10 @@ void mrmailbox_perform_smtp_jobs(mrmailbox_t* mailbox)
|
|||
{
|
||||
mrmailbox_log_info(mailbox, 0, ">>>>> SMTP-jobs started.");
|
||||
|
||||
pthread_mutex_lock(&mailbox->m_smtpidle_condmutex);
|
||||
mailbox->m_perform_smtp_jobs_needed = 0;
|
||||
pthread_mutex_unlock(&mailbox->m_smtpidle_condmutex);
|
||||
|
||||
mrjob_perform(mailbox, MR_SMTP_THREAD);
|
||||
|
||||
mrmailbox_log_info(mailbox, 0, "<<<<< SMTP-jobs ended.");
|
||||
|
@ -777,18 +800,25 @@ void mrmailbox_perform_smtp_idle(mrmailbox_t* mailbox)
|
|||
|
||||
pthread_mutex_lock(&mailbox->m_smtpidle_condmutex);
|
||||
|
||||
mailbox->m_smtpidle_in_idleing = 1; // checked in suspend(), for idle-interruption the pthread-condition below is used
|
||||
|
||||
int r = 0;
|
||||
struct timespec timeToWait;
|
||||
timeToWait.tv_sec = time(NULL)+60;
|
||||
timeToWait.tv_nsec = 0;
|
||||
while( mailbox->m_smtpidle_condflag == 0 && mailbox->m_smtpidle_suspend == 0 && r == 0 ) {
|
||||
r = pthread_cond_timedwait(&mailbox->m_smtpidle_cond, &mailbox->m_smtpidle_condmutex, &timeToWait); // unlock mutex -> wait -> lock mutex
|
||||
if( mailbox->m_perform_smtp_jobs_needed )
|
||||
{
|
||||
mrmailbox_log_info(mailbox, 0, "SMTP-idle skipped.");
|
||||
}
|
||||
mailbox->m_smtpidle_condflag = 0;
|
||||
else
|
||||
{
|
||||
mailbox->m_smtpidle_in_idleing = 1; // checked in suspend(), for idle-interruption the pthread-condition below is used
|
||||
|
||||
mailbox->m_smtpidle_in_idleing = 0;
|
||||
int r = 0;
|
||||
struct timespec timeToWait;
|
||||
timeToWait.tv_sec = time(NULL)+60;
|
||||
timeToWait.tv_nsec = 0;
|
||||
while( mailbox->m_smtpidle_condflag == 0 && mailbox->m_smtpidle_suspend == 0 && r == 0 ) {
|
||||
r = pthread_cond_timedwait(&mailbox->m_smtpidle_cond, &mailbox->m_smtpidle_condmutex, &timeToWait); // unlock mutex -> wait -> lock mutex
|
||||
}
|
||||
mailbox->m_smtpidle_condflag = 0;
|
||||
|
||||
mailbox->m_smtpidle_in_idleing = 0;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mailbox->m_smtpidle_condmutex);
|
||||
|
||||
|
@ -807,6 +837,11 @@ void mrmailbox_interrupt_smtp_idle(mrmailbox_t* mailbox)
|
|||
|
||||
pthread_mutex_lock(&mailbox->m_smtpidle_condmutex);
|
||||
|
||||
// when this function is called, it might be that the smtp-thread is in
|
||||
// perform_smtp_jobs(). if so, added jobs will be performed after the _next_ idle-jobs loop.
|
||||
// setting the flag perform_smtp_jobs_needed makes sure, idle() returns immediately in this case.
|
||||
mailbox->m_perform_smtp_jobs_needed = 1;
|
||||
|
||||
mailbox->m_smtpidle_condflag = 1;
|
||||
pthread_cond_signal(&mailbox->m_smtpidle_cond);
|
||||
|
||||
|
|
|
@ -48,14 +48,18 @@ struct _mrmailbox
|
|||
char* m_blobdir; /**< Full path of the blob directory. This is the directory given to mrmailbox_new() or a directory in the same directory as mrmailbox_t::m_dbfile. */
|
||||
|
||||
mrsqlite3_t* m_sql; /**< Internal SQL object, never NULL */
|
||||
mrimap_t* m_imap; /**< Internal IMAP object, never NULL */
|
||||
mrsmtp_t* m_smtp; /**< Internal SMTP object, never NULL */
|
||||
|
||||
mrimap_t* m_imap; /**< Internal IMAP object, never NULL */
|
||||
pthread_mutex_t m_imapidle_condmutex;
|
||||
int m_perform_imap_jobs_needed;
|
||||
|
||||
mrsmtp_t* m_smtp; /**< Internal SMTP object, never NULL */
|
||||
pthread_cond_t m_smtpidle_cond;
|
||||
pthread_mutex_t m_smtpidle_condmutex;
|
||||
int m_smtpidle_condflag;
|
||||
int m_smtpidle_suspend;
|
||||
int m_smtpidle_in_idleing;
|
||||
int m_perform_smtp_jobs_needed;
|
||||
|
||||
mrmailboxcb_t m_cb; /**< Internal */
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ mrmailbox_t* mrmailbox_new(mrmailboxcb_t cb, void* userdata, const char* os_name
|
|||
}
|
||||
|
||||
pthread_mutex_init(&ths->m_log_ringbuf_critical, NULL);
|
||||
pthread_mutex_init(&ths->m_imapidle_condmutex, NULL);
|
||||
pthread_mutex_init(&ths->m_smtpidle_condmutex, NULL);
|
||||
pthread_cond_init(&ths->m_smtpidle_cond, NULL);
|
||||
|
||||
|
@ -167,6 +168,7 @@ void mrmailbox_unref(mrmailbox_t* mailbox)
|
|||
mrsqlite3_unref(mailbox->m_sql);
|
||||
|
||||
pthread_mutex_destroy(&mailbox->m_log_ringbuf_critical);
|
||||
pthread_mutex_destroy(&mailbox->m_imapidle_condmutex);
|
||||
pthread_cond_destroy(&mailbox->m_smtpidle_cond);
|
||||
pthread_mutex_destroy(&mailbox->m_smtpidle_condmutex);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue