1
0
Fork 0
mirror of https://github.com/deltachat/deltachat-core.git synced 2025-10-06 12:00:11 +02:00

simplify cancellation of ongoing processes

This commit is contained in:
B. Petersen 2017-12-05 14:00:45 +01:00
parent a2ffdfe004
commit 9f07e59a0d
3 changed files with 129 additions and 120 deletions

View file

@ -241,7 +241,7 @@ int32_t mrmailbox_get_config_int (mrmailbox_t*, const char* key, int3
char* mrmailbox_get_version_str (void); char* mrmailbox_get_version_str (void);
int mrmailbox_configure_and_connect(mrmailbox_t*); int mrmailbox_configure_and_connect(mrmailbox_t*);
void mrmailbox_configure_cancel (mrmailbox_t*); void mrmailbox_stop_ongoing_process(mrmailbox_t*);
int mrmailbox_is_configured (mrmailbox_t*); int mrmailbox_is_configured (mrmailbox_t*);
void mrmailbox_connect (mrmailbox_t*); void mrmailbox_connect (mrmailbox_t*);
@ -326,7 +326,6 @@ mrcontact_t* mrmailbox_get_contact (mrmailbox_t*, uint32_t contact_id);
#define MR_BAK_PREFIX "delta-chat" #define MR_BAK_PREFIX "delta-chat"
#define MR_BAK_SUFFIX "bak" #define MR_BAK_SUFFIX "bak"
int mrmailbox_imex (mrmailbox_t*, int what, const char* param1, const char* param2); int mrmailbox_imex (mrmailbox_t*, int what, const char* param1, const char* param2);
void mrmailbox_imex_cancel (mrmailbox_t*);
char* mrmailbox_imex_has_backup (mrmailbox_t*, const char* dir); char* mrmailbox_imex_has_backup (mrmailbox_t*, const char* dir);
int mrmailbox_check_password (mrmailbox_t*, const char* pw); int mrmailbox_check_password (mrmailbox_t*, const char* pw);
char* mrmailbox_initiate_key_transfer(mrmailbox_t*); char* mrmailbox_initiate_key_transfer(mrmailbox_t*);
@ -352,6 +351,8 @@ int mrmailbox_get_thread_index (void);
int mrchat_set_draft (mrchat_t*, const char* msg); /* deprecated - use mrmailbox_set_draft() instead */ int mrchat_set_draft (mrchat_t*, const char* msg); /* deprecated - use mrmailbox_set_draft() instead */
#define mrpoortext_t mrlot_t #define mrpoortext_t mrlot_t
#define mrpoortext_unref mrlot_unref #define mrpoortext_unref mrlot_unref
#define mrmailbox_imex_cancel mrmailbox_stop_ongoing_process
#define mrmailbox_configure_cancel mrmailbox_stop_ongoing_process
/* library-internal */ /* library-internal */
@ -418,6 +419,11 @@ int mrmailbox_ensure_secret_key_exists (mrmailbox_t*); /* makes sure
char* mrmailbox_create_setup_code (mrmailbox_t*); char* mrmailbox_create_setup_code (mrmailbox_t*);
int mrmailbox_render_setup_file (mrmailbox_t* mailbox, const char* passphrase, char** ret_msg); int mrmailbox_render_setup_file (mrmailbox_t* mailbox, const char* passphrase, char** ret_msg);
extern int mr_shall_stop_ongoing;
int mrmailbox_alloc_ongoing (mrmailbox_t*);
void mrmailbox_free_ongoing (mrmailbox_t*);
#ifdef __cplusplus #ifdef __cplusplus
} /* /extern "C" */ } /* /extern "C" */
#endif #endif

View file

@ -358,10 +358,6 @@ cleanup:
******************************************************************************/ ******************************************************************************/
static int s_configure_running = 0;
static int s_configure_do_exit = 1; /* the value 1 avoids mrmailbox_configure_cancel() from stopping already stopped threads */
/** /**
* Configure and connect a mailbox. * Configure and connect a mailbox.
* *
@ -369,7 +365,7 @@ static int s_configure_do_exit = 1; /* the value 1 avoids mrmailbox_config
* using mrmailbox_set_config(). * using mrmailbox_set_config().
* *
* - mrmailbox_configure_and_connect() may take a while, so it might be a good idea to let it run in a non-GUI-thread; * - mrmailbox_configure_and_connect() may take a while, so it might be a good idea to let it run in a non-GUI-thread;
* to cancel the configuration progress, you can then use mrmailbox_configure_cancel(). * to stop the configuration progress, you can use mrmailbox_stop_ongoing_process().
* *
* - The function sends out a number of #MR_EVENT_CONFIGURE_PROGRESS events that may be used to create * - The function sends out a number of #MR_EVENT_CONFIGURE_PROGRESS events that may be used to create
* a progress bar or stuff like that. * a progress bar or stuff like that.
@ -399,33 +395,28 @@ int mrmailbox_configure_and_connect(mrmailbox_t* mailbox)
int success = 0, locked = 0, i; int success = 0, locked = 0, i;
int imap_connected_here = 0; int imap_connected_here = 0;
mrloginparam_t* param = mrloginparam_new(); mrloginparam_t* param = NULL;
char* param_domain = NULL; /* just a pointer inside param, must not be freed! */ char* param_domain = NULL; /* just a pointer inside param, must not be freed! */
char* param_addr_urlencoded = NULL; char* param_addr_urlencoded = NULL;
mrloginparam_t* param_autoconfig = NULL; mrloginparam_t* param_autoconfig = NULL;
#define PROGRESS(p) \
if( s_configure_do_exit ) { goto cleanup; } \
mailbox->m_cb(mailbox, MR_EVENT_CONFIGURE_PROGRESS, (p), 0);
if( mailbox == NULL ) { if( mailbox == NULL ) {
goto cleanup; return 0;
} }
if( !mrmailbox_alloc_ongoing(mailbox) ) {
return 0; /* no cleanup as this would call mrmailbox_free_ongoing() */
}
#define PROGRESS(p) \
if( mr_shall_stop_ongoing ) { goto cleanup; } \
mailbox->m_cb(mailbox, MR_EVENT_CONFIGURE_PROGRESS, (p), 0);
if( !mrsqlite3_is_open(mailbox->m_sql) ) { if( !mrsqlite3_is_open(mailbox->m_sql) ) {
mrmailbox_log_error(mailbox, 0, "Cannot configure, database not opened."); mrmailbox_log_error(mailbox, 0, "Cannot configure, database not opened.");
s_configure_do_exit = 1;
goto cleanup; goto cleanup;
} }
if( s_configure_running || s_configure_do_exit == 0 ) {
mrmailbox_log_error(mailbox, 0, "Already configuring.");
goto cleanup;
}
s_configure_running = 1;
s_configure_do_exit = 0;
/* disconnect */ /* disconnect */
mrmailbox_disconnect(mailbox); mrmailbox_disconnect(mailbox);
@ -454,6 +445,8 @@ int mrmailbox_configure_and_connect(mrmailbox_t* mailbox)
/* 1. Load the parameters and check email-address and password /* 1. Load the parameters and check email-address and password
**************************************************************************/ **************************************************************************/
param = mrloginparam_new();
mrsqlite3_lock(mailbox->m_sql); mrsqlite3_lock(mailbox->m_sql);
locked = 1; locked = 1;
@ -691,50 +684,11 @@ cleanup:
mrloginparam_unref(param_autoconfig); mrloginparam_unref(param_autoconfig);
free(param_addr_urlencoded); free(param_addr_urlencoded);
s_configure_do_exit = 1; /* avoids mrmailbox_configure_cancel() to stop the thread */ mrmailbox_free_ongoing(mailbox);
s_configure_running = 0;
return success; return success;
} }
/**
* Signal the configure-process to stop.
*
* After that, mrmailbox_configure_cancel() returns _without_ waiting
* for mrmailbox_configure_and_connect() to return.
*
* mrmailbox_configure_and_connect() will return ASAP then, however, it may
* still take a moment. If in doubt, the caller may also decide the kill the
* thread after a few seconds; eg. the configuration process may hang in a
* function not under the control of the core (eg. #MR_EVENT_HTTP_GET). Another
* reason for mrmailbox_configure_cancel() not to wait is that otherwise it
* would be GUI-blocking and should be started in another thread then; this
* would make things even more complicated.
*
* @memberof mrmailbox_t
*
* @param mailbox The mailbox object as created by mrmailbox_new()
*
* @return None
*/
void mrmailbox_configure_cancel(mrmailbox_t* mailbox)
{
if( mailbox == NULL ) {
return;
}
if( s_configure_running && s_configure_do_exit==0 )
{
mrmailbox_log_info(mailbox, 0, "Signaling the configure-process to stop ASAP.");
s_configure_do_exit = 1;
}
else
{
mrmailbox_log_info(mailbox, 0, "No configure-process to stop.");
}
}
/** /**
* Check if the mailbox is already configured. * Check if the mailbox is already configured.
* *
@ -769,3 +723,78 @@ int mrmailbox_is_configured(mrmailbox_t* mailbox)
return is_configured? 1 : 0; return is_configured? 1 : 0;
} }
/*
* Request an ongoing process to start.
* Returns 0=process started, 1=not started, there is running another process
*/
static int s_ongoing_running = 0;
int mr_shall_stop_ongoing = 1; /* the value 1 avoids mrmailbox_stop_ongoing_process() from stopping already stopped threads */
int mrmailbox_alloc_ongoing(mrmailbox_t* mailbox)
{
if( mailbox == NULL ) {
return 0;
}
if( s_ongoing_running || mr_shall_stop_ongoing == 0 ) {
mrmailbox_log_warning(mailbox, 0, "There is already another ongoing process running.");
return 0;
}
s_ongoing_running = 1;
mr_shall_stop_ongoing = 0;
return 1;
}
/*
* Frees the process allocated with mrmailbox_alloc_ongoing() - independingly of mr_shall_stop_ongoing.
* If mrmailbox_alloc_ongoing() fails, this function MUST NOT be called.
*/
void mrmailbox_free_ongoing(mrmailbox_t* mailbox)
{
s_ongoing_running = 0;
mr_shall_stop_ongoing = 1; /* avoids mrmailbox_stop_ongoing_process() to stop the thread */
}
/**
* Signal an ongoing process to stop.
*
* After that, mrmailbox_stop_ongoing_process() returns _without_ waiting
* for the ongoing process to return.
*
* The ongoing process will return ASAP then, however, it may
* still take a moment. If in doubt, the caller may also decide the kill the
* thread after a few seconds; eg. the process may hang in a
* function not under the control of the core (eg. #MR_EVENT_HTTP_GET). Another
* reason for mrmailbox_stop_ongoing_process() not to wait is that otherwise it
* would be GUI-blocking and should be started in another thread then; this
* would make things even more complicated.
*
* Typical ongoing processes are started by mrmailbox_configure_and_connect(),
* mrmailbox_initiate_key_transfer() or mrmailbox_imex(). As there is always at most only
* one onging process at the same time, there is no need to define _which_ process to exit.
*
* @memberof mrmailbox_t
*
* @param mailbox The mailbox object.
*
* @return None
*/
void mrmailbox_stop_ongoing_process(mrmailbox_t* mailbox)
{
if( mailbox == NULL ) {
return;
}
if( s_ongoing_running && mr_shall_stop_ongoing==0 )
{
mrmailbox_log_info(mailbox, 0, "Signaling the ongoing process to stop ASAP.");
mr_shall_stop_ongoing = 1;
}
else
{
mrmailbox_log_info(mailbox, 0, "No ongoing process to stop.");
}
}

View file

@ -35,10 +35,6 @@
#include "mrmimefactory.h" #include "mrmimefactory.h"
static int s_imex_running = 0;
static int s_imex_do_exit = 1; /* the value 1 avoids mrmailbox_imex_cancel() from stopping already stopped threads */
/******************************************************************************* /*******************************************************************************
* Autocrypt Key Transfer * Autocrypt Key Transfer
******************************************************************************/ ******************************************************************************/
@ -464,6 +460,10 @@ char* mrmailbox_create_setup_code(mrmailbox_t* mailbox)
* *
* For more details about the Autocrypt setup process, please refer to * For more details about the Autocrypt setup process, please refer to
* https://autocrypt.org/en/latest/level1.html#autocrypt-setup-message * https://autocrypt.org/en/latest/level1.html#autocrypt-setup-message
*
* NB: If the user has never sent a message before, this function requires a key to be created.
* In this case, the function may take some seconds to finish and it might be a good idea
* to start it in a separate thread. If so, it can be interrupted using mrmailbox_stop_ongoing_process().
*/ */
char* mrmailbox_initiate_key_transfer(mrmailbox_t* mailbox) char* mrmailbox_initiate_key_transfer(mrmailbox_t* mailbox)
{ {
@ -475,13 +475,25 @@ char* mrmailbox_initiate_key_transfer(mrmailbox_t* mailbox)
char* self_addr = NULL; char* self_addr = NULL;
uint32_t contact_id = 0; uint32_t contact_id = 0;
uint32_t chat_id = 0; uint32_t chat_id = 0;
mrmsg_t* msg = mrmsg_new(); mrmsg_t* msg = NULL;
if( (setup_code=mrmailbox_create_setup_code(mailbox)) == NULL if( !mrmailbox_alloc_ongoing(mailbox) ) {
|| !mrmailbox_render_setup_file(mailbox, setup_code, &setup_file_content) ) { return 0; /* no cleanup as this would call mrmailbox_free_ongoing() */
}
#define CHECK_EXIT if( mr_shall_stop_ongoing ) { goto cleanup; }
if( (setup_code=mrmailbox_create_setup_code(mailbox)) == NULL ) {
goto cleanup; goto cleanup;
} }
CHECK_EXIT
if( !mrmailbox_render_setup_file(mailbox, setup_code, &setup_file_content) ) {
goto cleanup;
}
CHECK_EXIT
if( (setup_file_name=mr_get_fine_pathNfilename(mailbox->m_blobdir, "autocrypt-setup-message.html")) == NULL if( (setup_file_name=mr_get_fine_pathNfilename(mailbox->m_blobdir, "autocrypt-setup-message.html")) == NULL
|| !mr_write_file(setup_file_name, setup_file_content, strlen(setup_file_content), mailbox) ) { || !mr_write_file(setup_file_name, setup_file_content, strlen(setup_file_content), mailbox) ) {
goto cleanup; goto cleanup;
@ -497,10 +509,14 @@ char* mrmailbox_initiate_key_transfer(mrmailbox_t* mailbox)
goto cleanup; goto cleanup;
} }
msg = mrmsg_new();
msg->m_type = MR_MSG_FILE; msg->m_type = MR_MSG_FILE;
mrparam_set (msg->m_param, MRP_FILE, setup_file_name); mrparam_set (msg->m_param, MRP_FILE, setup_file_name);
mrparam_set (msg->m_param, MRP_MIMETYPE, "application/autocrypt-setup"); mrparam_set (msg->m_param, MRP_MIMETYPE, "application/autocrypt-setup");
mrparam_set_int(msg->m_param, MRP_SYSTEM_CMD, MR_SYSTEM_AUTOCRYPT_SETUP_MESSAGE); mrparam_set_int(msg->m_param, MRP_SYSTEM_CMD, MR_SYSTEM_AUTOCRYPT_SETUP_MESSAGE);
CHECK_EXIT
if( mrmailbox_send_msg_object(mailbox, chat_id, msg) == 0 ) { if( mrmailbox_send_msg_object(mailbox, chat_id, msg) == 0 ) {
goto cleanup; goto cleanup;
} }
@ -514,6 +530,7 @@ cleanup:
mrmsg_unref(msg); mrmsg_unref(msg);
free(self_name); free(self_name);
free(self_addr); free(self_addr);
mrmailbox_free_ongoing(mailbox);
return setup_code; return setup_code;
} }
@ -817,7 +834,7 @@ static int export_backup(mrmailbox_t* mailbox, const char* dir)
stmt = mrsqlite3_prepare_v2_(dest_sql, "INSERT INTO backup_blobs (file_name, file_content) VALUES (?, ?);"); stmt = mrsqlite3_prepare_v2_(dest_sql, "INSERT INTO backup_blobs (file_name, file_content) VALUES (?, ?);");
while( (dir_entry=readdir(dir_handle))!=NULL ) while( (dir_entry=readdir(dir_handle))!=NULL )
{ {
if( s_imex_do_exit ) { if( mr_shall_stop_ongoing ) {
delete_dest_file = 1; delete_dest_file = 1;
goto cleanup; goto cleanup;
} }
@ -954,7 +971,7 @@ static int import_backup(mrmailbox_t* mailbox, const char* backup_to_import)
stmt = mrsqlite3_prepare_v2_(mailbox->m_sql, "SELECT file_name, file_content FROM backup_blobs ORDER BY id;"); stmt = mrsqlite3_prepare_v2_(mailbox->m_sql, "SELECT file_name, file_content FROM backup_blobs ORDER BY id;");
while( sqlite3_step(stmt) == SQLITE_ROW ) while( sqlite3_step(stmt) == SQLITE_ROW )
{ {
if( s_imex_do_exit ) { if( mr_shall_stop_ongoing ) {
goto cleanup; goto cleanup;
} }
@ -1057,7 +1074,7 @@ cleanup:
* - For each file written on export, the function sends #MR_EVENT_IMEX_FILE_WRITTEN * - For each file written on export, the function sends #MR_EVENT_IMEX_FILE_WRITTEN
* *
* Only one import-/export-progress can run at the same time. * Only one import-/export-progress can run at the same time.
* To cancel an import-/export-progress, use mrmailbox_imex_cancel(). * To cancel an import-/export-progress, use mrmailbox_stop_ongoing_process().
* *
* @memberof mrmailbox_t * @memberof mrmailbox_t
* *
@ -1077,19 +1094,15 @@ int mrmailbox_imex(mrmailbox_t* mailbox, int what, const char* param1, const cha
return 0; return 0;
} }
if( !mrmailbox_alloc_ongoing(mailbox) ) {
return 0; /* no cleanup as this would call mrmailbox_free_ongoing() */
}
if( param1 == NULL ) { if( param1 == NULL ) {
mrmailbox_log_error(mailbox, 0, "No Import/export dir/file given."); mrmailbox_log_error(mailbox, 0, "No Import/export dir/file given.");
return 0; return 0;
} }
if( s_imex_running || s_imex_do_exit==0 ) {
mrmailbox_log_warning(mailbox, 0, "Already importing/exporting.");
return 0;
}
s_imex_running = 1;
s_imex_do_exit = 0;
mrmailbox_log_info(mailbox, 0, "Import/export process started."); mrmailbox_log_info(mailbox, 0, "Import/export process started.");
mailbox->m_cb(mailbox, MR_EVENT_IMEX_PROGRESS, 0, 0); mailbox->m_cb(mailbox, MR_EVENT_IMEX_PROGRESS, 0, 0);
@ -1143,50 +1156,11 @@ int mrmailbox_imex(mrmailbox_t* mailbox, int what, const char* param1, const cha
cleanup: cleanup:
mrmailbox_log_info(mailbox, 0, "Import/export process ended."); mrmailbox_log_info(mailbox, 0, "Import/export process ended.");
s_imex_do_exit = 1; /* avoids mrmailbox_imex_cancel() to stop the thread */ mrmailbox_free_ongoing(mailbox);
s_imex_running = 0;
return success; return success;
} }
/**
* Signal the import-/export-process to stop.
*
* After that, mrmailbox_imex_cancel() returns _without_ waiting
* for mrmailbox_imex() to return.
*
* mrmailbox_imex() will return ASAP then, however, it may
* still take a moment. If in doubt, the caller may also decide the kill the
* thread after a few seconds; eg. the process may hang in a
* function not under the control of the core (eg. #MR_EVENT_HTTP_GET). Another
* reason for mrmailbox_imex_cancel() not to wait is that otherwise it
* would be GUI-blocking and should be started in another thread then; this
* would make things even more complicated.
*
* @memberof mrmailbox_t
*
* @param mailbox The mailbox object.
*
* @return None
*/
void mrmailbox_imex_cancel(mrmailbox_t* mailbox)
{
if( mailbox == NULL ) {
return;
}
if( s_imex_running && s_imex_do_exit==0 )
{
mrmailbox_log_info(mailbox, 0, "Signaling the import-/export-process to stop ASAP.");
s_imex_do_exit = 1;
}
else
{
mrmailbox_log_info(mailbox, 0, "No import-/export-process to stop.");
}
}
/** /**
* Check if there is a backup file. * Check if there is a backup file.
* *