diff --git a/src/manage_sql.c b/src/manage_sql.c index 82c446e79..12d794ca5 100644 --- a/src/manage_sql.c +++ b/src/manage_sql.c @@ -88,6 +88,18 @@ */ #define G_LOG_DOMAIN "md manage" +/** + * @brief Number of retries for + * LOCK TABLE .. IN ACCESS EXLUSIVE MODE NOWAIT + * statements. + */ +#define LOCK_RETRIES 16 + +/** + * @brief Time of delay between two lock retries. + */ +#define LOCK_RETRY_DELAY 2 + #ifdef DEBUG_FUNCTION_NAMES #include @@ -24449,7 +24461,7 @@ int delete_report (const char *report_id, int dummy) { report_t report; - int ret; + int ret, lock_ret, lock_retries; sql_begin_immediate (); @@ -24459,7 +24471,19 @@ delete_report (const char *report_id, int dummy) * * If the report is running already then delete_report_internal will * ROLLBACK. */ - sql ("LOCK table reports IN ACCESS EXCLUSIVE MODE;"); + lock_retries = LOCK_RETRIES; + lock_ret = sql_int ("SELECT try_exclusive_lock('reports');"); + while ((lock_ret == 0) && (lock_retries > 0)) + { + sleep(LOCK_RETRY_DELAY); + lock_ret = sql_int ("SELECT try_exclusive_lock('reports');"); + lock_retries--; + } + if (lock_ret == 0) + { + sql_rollback (); + return -1; + } if (acl_user_may ("delete_report") == 0) { @@ -29287,7 +29311,7 @@ copy_task (const char* name, const char* comment, const char *task_id, static int delete_task_lock (task_t task, int ultimate) { - int ret; + int ret, lock_ret, lock_retries; g_debug (" delete task %llu", task); @@ -29299,7 +29323,15 @@ delete_task_lock (task_t task, int ultimate) * * If the task is already active then delete_report (via delete_task) * will fail and rollback. */ - if (sql_error ("LOCK table reports IN ACCESS EXCLUSIVE MODE;")) + lock_retries = LOCK_RETRIES; + lock_ret = sql_int ("SELECT try_exclusive_lock('reports');"); + while ((lock_ret == 0) && (lock_retries > 0)) + { + sleep(LOCK_RETRY_DELAY); + lock_ret = sql_int ("SELECT try_exclusive_lock('reports');"); + lock_retries--; + } + if (lock_ret == 0) { sql_rollback (); return -1; @@ -29388,6 +29420,7 @@ int request_delete_task_uuid (const char *task_id, int ultimate) { task_t task = 0; + int lock_ret, lock_retries; /* Tasks have special handling for the trashcan. Other resources have trash * tables, like targets_trash. Tasks are marked as trash in the tasks table @@ -29463,13 +29496,27 @@ request_delete_task_uuid (const char *task_id, int ultimate) int ret; if (ultimate) - /* This prevents other processes (for example a START_TASK) from - * getting a reference to a report ID or the task ID, and then using - * that reference to try access the deleted report or task. - * - * If the task is running already then delete_task will lead to - * ROLLBACK. */ - sql ("LOCK table reports IN ACCESS EXCLUSIVE MODE;"); + { + /* This prevents other processes (for example a START_TASK) from + * getting a reference to a report ID or the task ID, and then + * using that reference to try access the deleted report or task. + * + * If the task is running already then delete_task will lead to + * ROLLBACK. */ + lock_retries = LOCK_RETRIES; + lock_ret = sql_int ("SELECT try_exclusive_lock('reports');"); + while ((lock_ret == 0) && (lock_retries > 0)) + { + sleep(LOCK_RETRY_DELAY); + lock_ret = sql_int ("SELECT try_exclusive_lock('reports');"); + lock_retries--; + } + if (lock_ret == 0) + { + sql_rollback (); + return -1; + } + } ret = delete_task (task, ultimate); if (ret)