Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix unprotected access to task_queue_.begin()->first in Scheduler #1084

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion erizo/src/erizo/thread/Scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ void Scheduler::serviceQueue() {
new_task_scheduled_.wait(lock);
}

current_timeout_ = task_queue_.begin()->first;
while (!stop_requested_ && !task_queue_.empty() &&
new_task_scheduled_.wait_until(lock, task_queue_.begin()->first) != std::cv_status::timeout) {
new_task_scheduled_.wait_until(lock, current_timeout_) != std::cv_status::timeout) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're not updating current_timeout_ within the loop, could it be an issue? what if someone adds an earlier task in the scheduler?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, that might be an issue. I don't know how we can correctly update the timeout for all threads when a new task is added. Maybe re-setting in the loop and do a notify_all on insert?

boost::thread::yield();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure why do we need to call yield() here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to give up our cpu time slice, since we are going to wait again

}
if (stop_requested_) {
break;
Expand All @@ -43,6 +45,10 @@ void Scheduler::serviceQueue() {
Function f = task_queue_.begin()->second;
task_queue_.erase(task_queue_.begin());

if (!task_queue_.empty()) {
current_timeout_ = task_queue_.begin()->first;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we wouldn't need to set current_timeout_ here, am I right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm starting to think we should still set it to the current worker but also signal the change to all other workers so they can update their timeout. But perhaps I'm overthinking it?

}

lock.unlock();
f();
lock.lock();
Expand Down
1 change: 1 addition & 0 deletions erizo/src/erizo/thread/Scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Scheduler {

private:
std::multimap<std::chrono::system_clock::time_point, Function> task_queue_;
std::chrono::system_clock::time_point current_timeout_;
std::condition_variable new_task_scheduled_;
mutable std::mutex new_task_mutex_;
std::atomic<int> n_threads_servicing_queue_;
Expand Down