Visitar URL original
Remove SLEEP status update from Regexp matches by headius · Pull Request #9948 · jruby/jruby · GitHub
Skip to content
Merged
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
23 changes: 9 additions & 14 deletions core/src/main/java/org/jruby/RubyThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -2072,34 +2072,29 @@ public default int run(ThreadContext context, Data data, byte[] bytes, int start
}

/**
* Execute an interruptible regexp operation with the given function and bytess.
* @param context
* @param matcher
* @param start
* @param range
* @param option
* @param task
* @return ""
* @param <Data>
* Execute an interruptible {@link RegexMatch} with the given parameters.
* @param context the current context
* @param matcher the matcher with which to perform the matching operation
* @param start the start of the match
* @param range the range of the match
* @param option option for the match
* @param task the interruptible match task to call
* @return an int result of the match operation
* @throws InterruptedException when interrupted
*/
public <Data> int executeRegexp(
public int executeRegexp(
ThreadContext context,
Matcher matcher, int start, int range, int option,
RegexMatch task) throws InterruptedException {
Status oldStatus = STATUS.get(this);
try {
this.unblockArg = matcher;
this.unblockFunc = task;

// check for interrupt before going into blocking call
blockingThreadPoll(context);

STATUS.set(this, Status.SLEEP);

return task.run(matcher, start, range, option);
} finally {
STATUS.set(this, oldStatus);
this.unblockFunc = null;
this.unblockArg = null;
pollThreadEvents(context);
Expand Down
40 changes: 40 additions & 0 deletions spec/ruby/language/regexp/interruptibility_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
require_relative '../../spec_helper'

describe "Regexp matching" do
before :each do
ready = Queue.new
input = 'a' * 1000 + '!'
@thread = Thread.new do
ready << true
# The backreference prevents caching from eliminating the backtracking.
/\A(a|aa)+\1\z/.match(input)
rescue RuntimeError => error
error
end

ready.pop
sleep 0.01 # Allow the thread to enter the regexp match.
end

after :each do
@thread.kill
@thread.join
end

it "keeps the thread status as run during a long match" do
@thread.status.should == 'run'
end

it "can be interrupted by Thread#raise during a long match" do
@thread.raise RuntimeError, 'interrupted'
@thread.join(5).should == @thread
@thread.value.should.is_a?(RuntimeError)
@thread.value.message.should == 'interrupted'
end

it "can be interrupted by Thread#kill during a long match" do
@thread.kill
@thread.join(5).should == @thread
@thread.status.should == false
end
end
Loading