5 ms·
For an embarrassing amount of time, I didn't even realize Java interrupt() could only interrupt blocking operations. I guess I thought they were like hardware i
by amarkov 8y ago
For an embarrassing amount of time, I didn't even realize Java interrupt() could only interrupt blocking operations. I guess I thought they were like hardware interrupts, capable of just showing up anywhere without the program's cooperation.
- AndrewBissell 8y agoWay back in the day this used to exist in Thread.stop(), which would kill threads in a hilariously indiscriminate manner. Long since deprecated: https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html https://docs.oracle.com/javase/8/docs/technotes/guides/concu...
- kuschku 8y agoSadly, sometimes Thread.stop is necessary. As a reminder, Thread.interrupt calls SocketChannel.close for any SocketChannel that is currently blocking. Let's check out how SocketChannel is implemented on Android: public synchronized int read(ByteBuffer target) ... public synchronized void close() ... Obviously, this causes a deadlock. The only alternative is using Thread.stop or completely creating your own SocketChannel implementation. This was fixed in Android N in 2016, but few users have that update yet (less than a quarter)
- pjmlp 8y agoThe problem is that only cooperative shutdown guarantees resources owned by threads are properly released without affecting the application's state.
- kuschku 8y agoSure, but I prefer 30-50LOC for cooperative shutdown of my socket thread over having to rewrite entire JDK APIs.
- pjmlp 8y agoThere I agree with you. This is one of the reasons why the process model is actually a much better approach.
- lomnakkus 8y agoGenerally agreed, but one should beware that even killing a process can still be quite destabilizing if that process was messing about with, say, shared memory. Still, at least those "dangerous situations" are a bit more obvious/explicit when we're talking about processes rather than threads where everything is shared by default.
- pjmlp 8y agoAgreed, I guess we as a community learned the hard way that threads, and what they imply (shared state) weren't a good idea after all.
- rsynnott 8y agoAre the Google employees who write Android’s standard lib not allowed talk to the Google employees who write Google’s Android apps, or something? My experience of Android is very limited, and I mostly do server-side Java stuff, but a number of times I’ve had a look at bugs on our Android stuff and it turns out to be some ridiculous Android standard lib design flaw/bug, usually fixed in later versions which few real-life Android users have (personal favourite; the bundled HTTP client didn’t work with a server with HTTP compression enabled for most “ok, but no content” responses (204 etc) until Android 4.2 or something). The people who write Google’s apps _have_ to be running into this stuff. But apparently either they’re not telling the standard lib people in a timely fashion, or they are but are being ignored.
- kllrnohj 8y agoWell for the interrupted() case the typical Android app never gets a close signal, it's just kill -9'd. So it's very plausible that simple no Google app ever noticed because thread.interrupt() is pretty unusual, and if nobody uses it nobody finds the edge cases. The Android standard lib these days is OpenJDK-based, but bugs still happen there, too. Even the best of standard libs still have bugs.
- DSMan195276 8y agoReminds me of this bug: https://android-review.googlesource.com/c/platform/bootable/bootloader/legacy/+/14699/1/libc/memset.c https://android-review.googlesource.com/c/platform/bootable/... Basically, when Android's libc was written they wrote `memset` wrong, such that it ignores the input parameter and always writes zeros. Nobody caught it for a while because, well, who calls `memset` with a non-zero value? There was HN thread about it (8 years ago apparently, I feel old...): https://news.ycombinator.com/item?id=1378912 https://news.ycombinator.com/item?id=1378912 The link itself is dead, but I managed to find the link to the code I posted above after a bit of searching.
- kuschku 8y agoThere are more funny bugs like that. For example, the result of "ab".split("") differs by android version. OpenJDK returns ["a", "b"], but older versions return ["", "a", "b"] and some even return ["", "a", "b", ""]. All this is strictly specified in the documentation and Java language specs, but no one ever bothered to fix it.
- ChuckMcM 8y agoThe discussions of Thread.stop() inside of the Java group during the run up to release were some of the most interesting ones to me as a systems guy (rather than as a language person, which was a more common specialization in the group). I got a much better appreciation for the halting problem from them. And while initially the view that "most of the time it will do what you expect" carried the day, that decision was reversed on appeal :-)
- smarks 8y agoI’m not sure what you mean by “reversed on appeal” as the stop() methods did make it into the platform. But there’s also Thread.destroy() whose API was defined but which I think was never actually implemented. (Fortunately.) Edit: FWIW, I looked through the history, and it looks like Thread.destroy() was added by Bill Joy in Aug 1995. The initial implementation was "throw new NoSuchMethodError();".
- lnanek2 8y agoIt's pretty clear he means it made it into the platform, then was later deprecated.
- derefr 8y agoIt's strange to deprecate something when you still can get exactly the same behavior by grabbing the thread's PID and then shelling out with a `kill -9`.
- lomnakkus 8y agoHow do you get a thread's PID in Java/on the JVM? Regardless, the deprecation serves as prominent warning that the programmer is about to shoot themselves in the foot. (I'm actually more surprised that stop() hasn't been removed after all this time.)
- derefr 8y agoOn a Java Card or other JVM-unikernel device, Thread.stop() would be the only way for a system watchdog process (e.g. an OOM killer) to be implemented.
- smarks 8y agoThere are narrow and unsafe uses of the no-arg Thread.stop() overload so it remains in the platform, although deprecated. There is an overload Thread.stop(Throwable) that is deprecated “for removal”. It’s been a no-op for several releases and the API will eventually be removed entirely.
- kitd 8y agoThread ID != process ID. Java 9 has introduced an API to get the process ID but before that, there was no defined way to get it, though it is accessible in a roundabout way via the JMX API, but even then it is not guaranteed. JNI would be another alternative.
- coldtea 8y agoThis argument doesn't make any sense. It's strange to deprecate something when you can still achieve the same effect in some roundabout way? Isn't that true for ALL APIs? You could always rewrite any deprecated API yourself, using sun.unsafe or JNI if it was needed, or even compile your own patched SDK fork. The main intend behind deprecation is telling people "we don't want to support this anymore and you shouldn't be using it". This is totally orthogonal to "you won't be able to replicate this behavior".