6666import org .joni .Matcher ;
6767import org .jruby .anno .JRubyClass ;
6868import org .jruby .anno .JRubyMethod ;
69+ import org .jruby .api .Create ;
6970import org .jruby .exceptions .MainExitException ;
7071import org .jruby .exceptions .RaiseException ;
7172import org .jruby .exceptions .ThreadKill ;
@@ -196,6 +197,8 @@ public enum Status {
196197 private final static AtomicReferenceFieldUpdater <RubyThread , Status > STATUS =
197198 AtomicReferenceFieldUpdater .newUpdater (RubyThread .class , Status .class , "status" );
198199
200+ private volatile boolean killed = false ;
201+
199202 /** Mail slot for cross-thread events */
200203 private final Queue <IRubyObject > pendingInterruptQueue = new ConcurrentLinkedQueue <>();
201204
@@ -278,9 +281,9 @@ private void executeInterrupts(ThreadContext context, boolean blockingTiming) {
278281
279282 if (err == UNDEF ) {
280283 // no error
281- } else if (err instanceof RubyFixnum && ((( RubyFixnum ) err ) .getLongValue () == 0 ||
282- (( RubyFixnum ) err ) .getLongValue () == 1 ||
283- (( RubyFixnum ) err ) .getLongValue () == 2 )) {
284+ } else if (err instanceof RubyFixnum fixErr && (fixErr .getLongValue () == 0 ||
285+ fixErr .getLongValue () == 1 ||
286+ fixErr .getLongValue () == 2 )) {
284287 toKill ();
285288 } else {
286289 if (getStatus () == Status .SLEEP ) {
@@ -318,7 +321,8 @@ private boolean pendingInterruptActive() {
318321
319322 private void toKill () {
320323 pendingInterruptClear ();
321- STATUS .set (this , Status .ABORTING );
324+ killed = true ;
325+ STATUS .set (this , Status .RUN );
322326 throwThreadKill ();
323327 }
324328
@@ -794,17 +798,13 @@ public void pollThreadEvents(ThreadContext context, boolean blocking) {
794798
795799 // CHECK_INTS
796800 public void pollThreadEvents (ThreadContext context ) {
797- killIfAborting ();
798-
799801 if (anyInterrupted ()) {
800802 executeInterrupts (context , false );
801803 }
802804 }
803805
804806 // RUBY_VM_CHECK_INTS_BLOCKING
805807 public void blockingThreadPoll (ThreadContext context ) {
806- killIfAborting ();
807-
808808 if (pendingInterruptQueue .isEmpty () && !anyInterrupted ()) {
809809 return ;
810810 }
@@ -814,19 +814,16 @@ public void blockingThreadPoll(ThreadContext context) {
814814 executeInterrupts (context , true );
815815 }
816816
817- private void killIfAborting () {
818- if (status == Status .ABORTING ) {
819- // currently aborting, resume abort
820- throwThreadKill ();
821- }
822- }
823-
824817 // RUBY_VM_INTERRUPTED_ANY
825818 private boolean anyInterrupted () {
826819 return Thread .interrupted () || (interruptFlag & ~interruptMask ) != 0 ;
827820 }
828821
829- private static void throwThreadKill () {
822+ /**
823+ * MRI: rb_threadptr_to_kill
824+ */
825+ private void throwThreadKill () {
826+ killed = true ;
830827 throw new ThreadKill ();
831828 }
832829
@@ -1373,7 +1370,7 @@ public RubyString inspect(ThreadContext context) {
13731370 result .catString (Integer .toString (line + 1 ));
13741371 }
13751372 result .cat (' ' );
1376- result .catString (getStatus (). toString (). toLowerCase ( ));
1373+ result .catString (getStatusName ( context ));
13771374 result .cat ('>' );
13781375 return result ;
13791376 }
@@ -1647,12 +1644,26 @@ public IRubyObject status() { // not used
16471644
16481645 @ JRubyMethod
16491646 public IRubyObject status (ThreadContext context ) {
1650- final Status status = getStatus ();
1651- if (threadImpl .isAlive () && status != Status .DEAD ) { // isAlive()
1652- return context .runtime .getThreadStatus (status );
1647+ if (status == Status .DEAD ) {
1648+ return exitingException != null ? context .nil : context .fals ;
16531649 }
16541650
1655- return exitingException != null ? context .nil : context .fals ;
1651+ return Create .newString (context , getStatusName (context ));
1652+ }
1653+
1654+ private String getStatusName (ThreadContext context ) {
1655+ Ruby runtime = context .runtime ;
1656+ final Status status = getStatus ();
1657+
1658+ switch (status ) {
1659+ case RUN :
1660+ if (killed ) {
1661+ return "aborting" ;
1662+ }
1663+ // fall through
1664+ default :
1665+ return status .name ().toLowerCase ();
1666+ }
16561667 }
16571668
16581669 @ JRubyMethod (meta = true , omit = true )
@@ -1952,14 +1963,17 @@ private Status nativeStatus() {
19521963 @ JRubyMethod (name = {"kill" , "exit" , "terminate" })
19531964 public IRubyObject kill () {
19541965 Ruby runtime = getRuntime ();
1955- // need to reexamine this
1956- RubyThread currentThread = runtime .getCurrentContext ().getThread ();
19571966
1958- if (currentThread == runtime . getThreadService (). getMainThread () ) {
1959- // rb_exit to hard exit process...not quite right for us
1967+ if (killed == true || status == Status . DEAD ) {
1968+ return this ;
19601969 }
19611970
1962- STATUS .set (this , Status .ABORTING );
1971+ ThreadContext context = runtime .getCurrentContext ();
1972+ RubyThread currentThread = context .getThread ();
1973+
1974+ if (this == runtime .getThreadService ().getMainThread ()) {
1975+ RubyKernel .exit (context , runtime .getKernel (), Helpers .arrayOf (RubyFixnum .zero (runtime )));
1976+ }
19631977
19641978 return genericKill (runtime , currentThread );
19651979 }
0 commit comments