The prevailing religion of Java today heavily forbids the use of the stop() instance method on a Thread[1] [2] [3]. It's marked as Deprecated in the official documentation, with a message that begins with:
This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. [...]
There is even a whole article supplied that goes into further detail. (Especially that ThreadDeath is silent when it gets to the top, and even if you guard against it, you can't guard against Thread.stop(Throwable t) anyway.)
In general, I agree with what that article is worried about, and with the answers to the related question on StackOverflow — in almost all the use cases in the world there is a much better way than stop(). But not all.
Here is a use case that I'm struggling to think of a better way for. I invite your suggestions.
Use case
I'm working with an interactive console running on top of Java, that allows the user run arbitrary Java statements and Python functions that call Java, in an interactive interpreted way. (See Jython console for screenshots.)
Now, the user can write arbitrary functions. Some of them might call Java methods that result in infinite loops that print a lot of output, almost saturating the system, so that it becomes painfully slow to respond.
When the user messes up like this, I need to give them a chance to kill the thread (using a button), and salvage the remainder of the work that they have produced in their session and stored in local variables.
If calling interrupt() on the thread fails, (e.g. if it never goes into waiting state while stuck in its infinite loop), then we are faced with two options that I can see: (1) kill the application outright or (2) use stop() on the bad thread, and let the user salvage whatever is left that hadn't been corrupted.
Yes I know that some objects may have been damaged and won't work properly. But we're talking about salvaging anything that may have been left in a valid state (which is probably pretty much everything, except one or two things).
Can anybody see any problems with this reasoning? And if this turns out to be a valid use-case, then does it mean the method shouldn't be deprecated :) ?
Calling Thread.stop() is a bad idea. End of story.
It may work in practice but you sacrifice most of the JVM's concurrency guarantees in the process. Your whole program is essentially running undefined behavior. It isn't simply the thread or the data in the thread that may become corrupted, but any part of the JVM that happens to be in a vulnerable state when the thread is killed.
It sounds like you're looking for someone to confirm that your use case somehow avoids the risks to the JVM. It doesn't, so you're not likely to get such a confirmation. If you don't see issues more power to you, but don't be surprised when it fails in inexplicable or dangerous ways.
As Peter Lawrey suggests you should be running this untrusted code in an isolated JVM, where the OS's process management can support killing resource-hogging processes. If you can't do that because you're passing around strange resources like open file descriptors that is your problem.
Related
In our Netty application. We are moving all blocking calls in our code to run in a special backgroundThreadGroup.
I'd like to be able to log in production the threadName and the lineNumber of the java code that is about to execute a blocking operation. (i.e. sync File and Network IO)
That way I can grep for the logs looking at places were we might have missed to move our blocking code to the backgroundThreadGroup.
Is there a way to instrument the JVM so that it can tell me that?
Depends on what you mean by a "blocking operation".
In a broad sense, any operation that causes a voluntary context switch is blocking. Trying to do something special about them is absolutely impractical.
For example, in Java, any method containing synchronized is potentially blocking. This includes
ConcurrentHashMap.put
SecureRandom.nextInt
System.getProperty
and many more. I don't think you really want to avoid calling all these methods that look normal at a first glance.
Even simple methods without any synchronization primitives can be blocking. E.g., ByteBuffer.get may result in a page fault and a blocking read on the OS level. Furthermore, as mentioned in comments, there are JVM level blocking operations that are not under your control.
In short, it's impractical if not impossible to find all places in the code where a blocking operation happens.
If, however, you are interested in finding particular method calls that you believe are bad (like Thread.sleep and Socket.read), you can definitely do so. There is a BlockHound project specifically for this purpose. It already has a predefined list of "bad" methods, but can be customized with your own list.
There is a library called BlockHound, that will throw an exception unless you have configured BlockHound to ignore that specific blocking call
This is how you configure BlockHound for Netty: https://github.com/violetagg/netty/blob/625f9d5781ed85bfaca6fa4e826d0d46d70fdbd8/common/src/main/java/io/netty/util/internal/Hidden.java
(You can improve the above code by replacing the last line with builder.nonBlockingThreadPredicate(
p -> p.or(thread -> thread instanceof FastThreadLocalThread)); )
see https://github.com/reactor/BlockHound
see https://blog.frankel.ch/blockhound-how-it-works/
I personally used it to find all blocking call within our Netty based service.
Good Luck
Thread.stop() is now removed from modern Android API. From https://developer.android.com/reference/java/lang/Thread#stop(),
Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, ...
I suppose that a complete removal of a method must be backed by an alternative of it, both for the many uses where it is replaceable, and for the many other uses where it is not. I am therefore wondering what is the alternative of Thread.stop() that stops a thread where cooperative interruption flags do not work, which is possibly due to e.g. calls of slow 3rd-party functions.
From the articles I've googled and the duplicated SO questions I've read about this issue, I got only two unsatisfactory types of answers:
You should just consider cooperative interruption because it's not stupid.
Thread.stop() is now gone for whatever reason so just forget it.
I would appreciate a lot if you could either provide a functioning alternative of Thread.stop() or explain the rationale behind removing it despite the legitimate use cases depending on it, where "legitimate" implies nonexistence of any synchronization and locking issue.
Thanks in advance.
There is no "modern" alternative. The old alternatives are still the only ones. Why? Because this is fundamentally an unsolvable problem1 ... if the threads are not cooperating / checking for thread interrupts, or if they unable to correctly deal with a thread interrupt.
For the record, the technical reasons that Thread.stop() is unsafe include:
It breaks mutual exclusion locks help by the thread being stopped. This may leave the object that was locked ... or other objects ... in an inconsistent state.
It may result in broken inter-thread signalling. For example, if a thread is expected to notify a condition variable, and it gets stopped before this happen, then other threads may be stuck forever waiting for a notify that never arrives.
If has said that, issues such as the above can in theory be addressed by application code on a case-by-base basis. For example, if you were using stop() you could catching ThreadDeath in all of the necessary places, take remedial action and then rethrow it. But to borrow someone else's words, "it would be insanely messy".
I'm sorry if you think this is all unsatisfactory. But this is life. If you cannot write your threads to be cooperative, and you need them to be killable, run them in an external process, via Process etcetera.
Now ... if we could wave a magic wand and replace Java threads with a CSP-like model of concurrency (and in doing so, eschew state sharing between processes), then the problem goes away. Though now you have to deal with the other problem of what to do with the messages queued up when a process is terminated. But at least that is a tractable problem.
1 - I am asserting this without proof! However, if it was a solvable problem, then you would have thought that Sun or Oracle or Google would have discovered and implemented a solution in the last ... umm ... 25 years. Challenge: If you can come up with a viable implementation model for safely killing Java threads, I expect that certain companies would be willing to offer you a very well-paid job. Especially if they can secure exclusive rights on your patent.
Summary
From my studies, I don't remember that a concept such "uninterruptible block" exists, and I did not find it either with a quick Google search.
Expected answer
yes, it does exist, and the proper term for that is ... (in this case, it would be nice, if someone could explain me, why it does not exist in Java)
no, it does not exist, because ...
Definition
By "uninterruptible block", I mean a section of code, in a multi-threading context, which, once starts execution, cannot be interrupted by other threads. I.e., the CPU (or the JVM), won't run any other thread at all, until the "atomic block" is left.
Note, that this is not the same as a section marked by lock/mutex/... etc., because such section can not be interrupted only by other threads, which acquire the same lock or mutex. But other threads can still interrupt it.
EDIT, in response to comments It would be fine also, if it affected only the threads of the current process.
RE. multiple cores: I would say, yes, also the other cores should stop, and we accept the performance hit (or, if it is exclusive only for the current process, then the other cores could still run threads of other processes).
Background
First of all, it is clear, that, at least in Java, this concept does not exist:
Atomic as in uninterruptible: once the block starts, it can't be interrupted, even by task switching.
...
[this] cannot be guaranteed in Java - it doesn't provide access to the
"critical sections" primitives required for uninterruptibility.
However, it would have come in handy in the following case: a system sends a request and receives response A. After receiving the response, it has max. 3 seconds to send request B. Now, if multiple threads are running, doing this, then it can happen, that after receiving response A, the thread is interrupted, and one or more threads run, before the original thread has the chance to send out request B, and thus misses the 3 seconds deadline. The more threads are running, the bigger the risk that this happens. By marking the "receive A to send B" section "uninterruptible", this could be avoided.
Note, that locking this section would not solve the issue. (It would not prevent the JVM, from e.g. processing 10 new threads at the "send request A" phase, right after our thread received response A.)
EDIT: Re. global mutex. That would also not solve the issue. Basically, I want the threads to make Request A's (and some other stuff) simultaneously, but I want them to stop, when another thread received Response A, and is going to make Request B.
Now, I know, that this would not be a 100% solution either, because those threads that don't get scheduled right after receiving response A still could miss the deadline. But, at least, those who do, would for sure send out the second request in time.
Some further speculation
The classic concurrency problem a++ could be simply solved by uninterruptible { a++; }, without the need for locks (which can cause dead-lock, and, in any case, would probably be more expensive in terms of performance, than simply executing the three instructions required by a++, with a simple flag, that they must not be interrupted).
EDIT RE. CAS: of course, that's another solution too. However, it involves retrying, until the write succeeds, and it is also slightly more complex to use (at least in Java, we have to use AtomicXXX, instead of the primitive types for that).
I know, of course, that this could be easily abused, by marking large blocks of code as uninterruptible, but that is true for many concurrency primitives as well. (What's more, I also know, that my original use case would be also kind of an "abuse", since I'd be doing I/O in an uninterruptible block, still it would have been worth at least a try, if such concept did exist in Java.)
I am using Android Studio (intelliJ-idea) for Android development. I get a warning for this piece of code:
if (status == STATUS_SOLVING) {
if (!solverThread.isAlive())
if (status != STATUS_SOLVED) // <<<<<< WARNING THIS LINE
status = STATUS_DATA_COLLECTING;
}
The line indicated above gives me a warning, saying that this condition is always true. I can see why this is true if the whole program runs on a single thread.
But since my program uses a parallel thread to change the value of status, does it not mean that this condition might change between line #1 and #3 in the snippet above?
Is this a valid warning? Am I missing something?
Do things change if I change the nested ifs into one single if with && operator?
It means that if you're counting on a value being changed by another thread that's a dangerous programming tactic and that the compiler won't know that its being accessed by different friends and will optimize assuming it isn't.
Any variable that may be touched by multiple threads like that needs to be declared volatile to inform the compiler that its touched by multiple threads, and special care needs to be taken in treating it. If you didn't know that I'll bet you have a dozen other multithreading bugs waiting to happen.
If a second thread is involved and changes status then certainly the value can change between lines 1 and 3. Especially since you don't seem to have any kind of thread synchronization in place, deliberate or not.
Granted, the code seems a bit unsafe, because you would not normally have two threads accessing the same variable without some kind of concurrency control. But this is speculation since I don't see the rest of your code.
Anyway, this is a warning, not an error. Sometimes warnings are wrong, that's why they can be suppressed.
You could see this as a sign that you're up to some unsafe stuff though. Perhaps you could post some more code in case you want to discuss the actual synchronization aspects?
I am experimenting with a game mechanic in which players can run scripts on in-game computers. Script execution will be resource limited at a gameplay level to some amount of instructions per tick.
The following proof-of-concept demonstrates a basic level of sandboxing and throttling of arbitrary user code. It successfully runs ~250 instructions of poorly crafted 'user input' and then discards the coroutine. Unfortunately, the Java process never terminates. A little investigation in shows that the LuaThread created by LuaJ for the coroutine is hanging around forever.
SandboxTest.java:
public static void main(String[] args) {
Globals globals = JsePlatform.debugGlobals();
LuaValue chunk = globals.loadfile("res/test.lua");
chunk.call();
}
res/test.lua:
function sandbox(fn)
-- read script and set the environment
f = loadfile(fn, "t")
debug.setupvalue(f, 1, {print = print})
-- create a coroutine and have it yield every 50 instructions
local co = coroutine.create(f)
debug.sethook(co, coroutine.yield, "", 50)
-- demonstrate stepped execution, 5 'ticks'
for i = 1, 5 do
print("tick")
coroutine.resume(co)
end
end
sandbox("res/badfile.lua")
res/badfile.lua:
while 1 do
print("", "badfile")
end
The docs suggest that a coroutine that is considered unresumable will be garbage collected and an OrphanedThread exception will be thrown, signalling the LuaThread to end - but this is never happening. My question is in two parts:
Am I doing something fundamentally wrong to cause this behaviour?
If not, how should I handle this situation? From the source it appears that if I can get a reference to the LuaThread in Java I may be able to forcibly abandon it by issuing an interrupt(). Is this a good idea?
Reference: Lua / Java / LuaJ - Handling or Interrupting Infinite Loops and Threads
EDIT: I have posted a bug report over at the LuaJ SourceForge. It discusses the underlying issue (threads not being garbage collected as in the Lua spec) and suggests some ways to work around it.
It seems to be a limitation of LuaJ. I submitted a ticket earlier this year on Sourceforge as I see you've also done. The LuaThread class doesn't store references to the Java threads it creates, so you can't interrupt() those threads without modifying the LuaJ core to expose them:
new Thread(this, "Coroutine-"+(++coroutine_count)).start();
It may be dangerous to interrupt those threads without adding appropriate cleanup code to LuaJ.
Documentation that you provided for OrphanedThread also tells us that scope is the defining condition:
"Error sublcass that indicates a lua thread that is no longer referenced has been detected. The java thread in which this is thrown should correspond to a LuaThread being used as a coroutine that could not possibly be resumed again because there are no more references to the LuaThread with which it is associated. Rather than locking up resources forever, this error is thrown, and should fall through all the way to the thread's Thread.run() method."
Your code example doesn't cause all LuaThread references to disappear, so you shouldn't expect an exception to be thrown. CoroutineLib documentation indicates: Coroutines that are yielded but never resumed to complete their execution may not be collected by the garbage collector, so an OutOfMemoryError should actually be expected from the code you listed on SourceForge, if I'm not mistaken. LuaThread:52 also specifies: Applications should not catch OrphanedThread, because it can break the thread safety of luaj., which is yet another obstacle.
There also seem to be differences between empty and non-empty while loops in Lua/J. IIRC, empty loops (while true do end) don't obey all coroutine hook/tick rules. *Because no actions occur in an empty loop, there's no opportunity for certain hooks to occur (I need to test this again so please correct me otherwise!).
A forked version of LuaJ with the functionality we're looking for is used in the ComputerCraft mod for Minecraft, though it's designed only for the mod and isn't open source.