Fix for corner case where executing task will occupy not one but two threads in the pool which are in short supply.

This commit is contained in:
Silviu Caragea 2018-03-22 22:26:03 +02:00
parent a2dc16a582
commit 24de8d624f
2 changed files with 23 additions and 3 deletions

View File

@ -49,10 +49,14 @@ bool BackgroundSchedulePool::TaskInfo::schedule()
scheduled = true;
if (delayed)
pool.cancelDelayedTask(shared_from_this(), lock);
if(!executing)
{
if (delayed)
pool.cancelDelayedTask(shared_from_this(), lock);
pool.queue.enqueueNotification(new TaskNotification(shared_from_this()));
}
pool.queue.enqueueNotification(new TaskNotification(shared_from_this()));
return true;
}
@ -103,6 +107,7 @@ void BackgroundSchedulePool::TaskInfo::execute()
return;
scheduled = false;
executing = true;
}
CurrentMetrics::Increment metric_increment{CurrentMetrics::BackgroundSchedulePoolTask};
@ -116,6 +121,20 @@ void BackgroundSchedulePool::TaskInfo::execute()
if (milliseconds >= slow_execution_threshold_ms)
LOG_INFO(&Logger::get("BackgroundSchedulePool"), "Executing " << name << " took " << milliseconds << " ms.");
{
std::lock_guard lock_schedule(schedule_mutex);
executing = false;
/// In case was scheduled while executing (including a scheduleAfter which expired) we schedule the task
/// on the queue. We don't call the function again here because this way all tasks
/// will have their chance to execute
if(scheduled && !deactivated)
pool.queue.enqueueNotification(new TaskNotification(shared_from_this()));
}
}
zkutil::WatchCallback BackgroundSchedulePool::TaskInfo::getWatchCallback()

View File

@ -72,6 +72,7 @@ public:
bool deactivated = false;
bool scheduled = false;
bool delayed = false;
bool executing = false;
BackgroundSchedulePool & pool;
Task function;