4 ms·
Sadly, sometimes Thread.stop is necessary. As a reminder, Thread.interrupt calls SocketChannel.close for any SocketChannel that is currently blocking. Let's c
by kuschku 9y ago
Sadly, 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 9y agoThe problem is that only cooperative shutdown guarantees resources owned by threads are properly released without affecting the application's state.
- kuschku 9y agoSure, but I prefer 30-50LOC for cooperative shutdown of my socket thread over having to rewrite entire JDK APIs.
- pjmlp 9y agoThere I agree with you. This is one of the reasons why the process model is actually a much better approach.
- lomnakkus 9y 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 9y 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 9y 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 9y 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 9y 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 9y 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.