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.
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.
- duplicates
-
JDK-4965960 Bring JSR-166 up to date with Public Review Jan 2004
-
- Resolved
-