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

TimerTask: kill the execution when it exceeds the task timeout #749

Closed
wants to merge 3 commits into from

Conversation

rubemz
Copy link
Contributor

@rubemz rubemz commented Jul 13, 2018

Before this commit when a TimerTask task exceeded the timeout the job kept running. That could lead to thread leaking. Related to #639

This PR changes the TimerTask executor to be a SingleThreadExecutor. So whenever the task doesn't finish in time, the execution thread is killed (in this case the pool is killed).

The spec ensures that this new behavior is working correctly. It fails on master. If the main job isn't killed after the timeout, the latch.wait(2) would raise, since the timer task sleeps for 5 seconds.

If you want to see the leak by yourself take a look on this https://github.com/rubemz/concurrent-ruby-leak, which is pretty much a copy from #639 (comment). @shun0309 thanks for that code.

Closes #639

…d timer_task timeout specs

Before this commit when a TimerTask task exceeded the timeout the job
kept running. That could lead to thread leaking. Related to ruby-concurrency#639

This PR changes the TimerTask executor to be a SingleThreadExecutor. So
whenever the task doesn't finish in time, the execution thread is killed
(in this case the pool is killed)

The spec ensures that this new behavior is working correctly. It fails
on master. If the main job isn't killed after the timeout, the
latch.wait(2) would raise, since the main task sleeps for 5 seconds.

Closes ruby-concurrency#639
@rubemz rubemz force-pushed the fix/timer-task-leaking branch from c772e76 to 5a65b76 Compare July 13, 2018 17:11
@@ -325,6 +339,10 @@ def execute_task(completion)
def timeout_task(completion)
return unless @running.true?
if completion.try?
@executor.kill
@executor.wait_for_termination
@executor = Concurrent::RubySingleThreadExecutor.new()
Copy link

Choose a reason for hiding this comment

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

Maybe just new?

Copy link
Contributor

Choose a reason for hiding this comment

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

(also line 284)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@pitr-ch
Copy link
Member

pitr-ch commented Jul 13, 2018

Thanks for the fix, I'll have a look in couple of days.

@pitr-ch pitr-ch self-requested a review July 15, 2018 15:20
@ghost ghost added the in progress label Jul 17, 2018
@pitr-ch
Copy link
Member

pitr-ch commented Aug 21, 2018

Hi, sorry I did not forgot about your PR. I needed to get out 1.1.0.pre1 for testing. I'll review the PR soon.

@@ -280,7 +280,8 @@ def ns_initialize(opts, &task)
self.execution_interval = opts[:execution] || opts[:execution_interval] || EXECUTION_INTERVAL
self.timeout_interval = opts[:timeout] || opts[:timeout_interval] || TIMEOUT_INTERVAL
@run_now = opts[:now] || opts[:run_now]
@executor = Concurrent::SafeTaskExecutor.new(task)
@task = task
@executor = Concurrent::RubySingleThreadExecutor.new
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs a corresponding change to the require statements at top of this file (remove concurrent/executor/safe_task_executor, add concurrent/executor/ruby_single_thread_executor)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@wjordan thanks. fixed in 9e2fd1c

@pitr-ch
Copy link
Member

pitr-ch commented Oct 10, 2018

Sorry still did not find time to do a proper review. There is a problem with killing threads, if it's killed while running e.g. ensure block it may corrupt data and other unpleasant things (more info e.g. https://www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/). I need to give this a more careful thought.

@chrisseaton
Copy link
Member

We removed timer timeouts in #926 given their problems.

We're open to discussing more options.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Thread leaks in TimerTask for long-executing jobs
6 participants