JDK-4176863 : (thread) Thread.currentThread().interrupt() should always be allowed
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.2.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: solaris_2.5
  • CPU: sparc
  • Submitted: 1998-09-28
  • Updated: 2004-02-20
  • Resolved: 2004-02-20
Related Reports
Duplicate :  
Description
Regardless of what thread or security context it is executing in, code should
always be able to set the "interrupted" flag of the current thread, so that it
can follow the proper, recommended procedure for propagating interrupts
received via an InterruptedException or an InterruptedIOException that it is
not going to handle (and those exceptions are not declared to be thrown by the
current method), but the current implementation of the Thread.interrupt()
method always calls Thread.checkAccess(), which invokes the checkAccess() on
the current security manager with this Thread instance, which could throw a
security exception, depending on the protection domains in the current access
control context and the security manager's implementation (the default
java.lang.SecurityManager will deny such access to threads in the system
thread group without "modifyThread" permission).

For example, the "Java Thread Deprecation White Paper" contains the following
passage relating to how to handle thread interrupts:
 
        For this technique to work, it's critical that any method that
        catches an interrupt exception and is not prepared to deal with
        it immediately reasserts the exception. We say reasserts rather
        than rethrows, because it is not always possible to rethrow the
        exception. If the method that catches the InterruptedException
        is not declared to throw this (checked) exception, then it
        should "reinterrupt itself" with the following incantation:
 
                Thread.currentThread().interrupt();
 
        This ensures that the Thread will reraise the
        InterruptedException as soon as it is able.

A well-behaved piece of library code might want to follow this pattern
if it happens to do some I/O and it gets an InterruptedIOException,
because it has no desire to influence how an interrupt to the current
should be handled, but it wants to propagate the fact of the interrupt
to its caller.  But it could be executing in any arbitrary thread, say
perhaps a system callback thread, with an unknown security manager and
protection domains on the stack, so the above code could cause a
(unchecked) security exception to be thrown if the security manager
denies "access" to the current thread, rendering this valuable approach
dangerous to use.  In some cases, a doPrivileged() block would help,
but not if the library code itself isn't trusted by the security
manager implementation to interrupt the thread.

To solve this problem, Thread.interrupt() should not call checkAccess() if it
is being invoked on the current thread.  This would allow the safe usage of the
recommended idiom for propagating thread interrupts, and it would not open up a
security hole: setting the interrupted flag on the current thread is no less
harmful than many other denials of service that untrusted code can already
undertake on the thread that it is executing in, such as throwing unchecked
exceptions or going into infinite loops.  Note that no security check
guards the ability to *clear* the interrupted flag of the current
thread (with Thread.isInterrupted()); I presume that this is because
the API limits the operation to the current thread anyway, so it's not
considered particularly dangerous.

Comments
WORK AROUND Make sure that the code that needs to self-interrupt is allowed to do so by the security manager, either by choosing a particular security manager class or by granting the code the "modifyThread" RuntimePermission (likely to be too broadly permissive). If the code itself already has the necessary permission (such as if it is system code), then maybe the invocation of Thread.interrupt() just needs to be enclosed in a doPrivileged() block so that the other protection domains on the stack do not cause the security check to fail.
11-06-2004

SUGGESTED FIX Only call the checkAccess() method in Thread.interrupt() if "this" is not the current thread: public void interrupt() { if (this != currentThread()) { checkAccess(); } interrupt0(); }
11-06-2004

PUBLIC COMMENTS Regardless of what thread or security context it is executing in, code should always be able to set the "interrupted" flag of the current thread, so that it can follow the proper, recommended procedure for propagating interrupts received via an InterruptedException or an InterruptedIOException that it is not going to handle (and those exceptions are not declared to be thrown by the current method), but the current implementation of the Thread.interrupt() method always calls Thread.checkAccess(), which invokes the checkAccess() on the current security manager with this Thread instance, which could throw a security exception, depending on the protection domains in the current access control context and the security manager's implementation (the default java.lang.SecurityManager will deny such access to threads in the system thread group without "modifyThread" permission).
10-06-2004

EVALUATION This was fixed as part of the changes for 4965960: Bring JSR-166 up to date with Public Review Jan 2004 I intend to close it as a duplicate of that bug soon. ###@###.### 2004-02-13 The fixes for 4965960 will be in tiger b40, so users of tiger beta2 should get it. ###@###.### 2004-02-20
13-02-2004