During debugging of Android app, sometimes InterruptedException occurs and crashes the app. I've been able to set a break-point on default exception handler, but call stack is not informative.
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.reportInterruptAfterWait(AbstractQueuedSynchronizer.java:1991)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2025)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1048)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:776)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1035)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1097)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:820)
What is telling is that the interrupted thread is always RxCachedThreadScheduler-4 (or some other number)
What would be a systematic approach towards finding the root cause of the exception?
Set breakpoint at the method Thread::interrupt and catch the offender. If you think that this interruption should not happen, and you cannot switch off the call which interrupts your thread, then you can override Thread::interrupt in your thread implementation, and force the the thread pool to use your implementation by providing your own ThreadFactory.
It looks like the crash is happening from a third party code package, you should post your issue with the source project as well for additional help. Please post any code related to how you use this package to help troubleshoot too. Make sure you're using the latest version of this package in case they already fixed this issue. The stack trace isn't very helpful because the other project is launching threads and the crash happens from within one of their threads. Likely, you're not using the package as intended or there is a bug in it that they need to fix.
https://github.com/ReactiveX/RxJava
Related
I have in my app an occasional and very hard to reproduce ANR event. Today it's happened, and I pulled out from the device the file trace.txt situated in /data/anr.
Unfortunately I can't understand the data in this file, here is the complete file content.
Can someone understand what is keeping my app's UI unresponsive?
I've already read similar questions but still can't read the file..
I've pasted the complete trace.txt file content to pastebin
EDIT
the file on pastebin is not available anymore and I do not have access to the trace.txt file anymore, so the answer can be closed.
thank you
You can use Strictmode to find out what calls delay a specific thread. The best way to use it is in the following form. In your application onCreate() you enable StrictMode. After that, (almost) all slow calls on that thread will be reported to your Log, with a full stacktrace of where it happened.
In your custom Application class:
public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll() // detect everything potentially suspect
.penaltyLog() // penalty is to write to log
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog()
.build());
}
super.onCreate();
}
As #Mohamed_AbdAllah has written on his comment "trace.txt is the situation of all running threads when the ANR occurred." Finding the reason of ANR from a thread while ANR occured seems impossible with a trace like you post. If you want to understand what those texts in trace mean, you may be interested in this. (You can get which thread is long running when the ANR occured from trace but this probably does not help you)
Alternatively, if you want to see what type of crashes/ANRs do you have with your andoid application(I assume that you are interested in applications that you developped and published on google play) you can use a crash report api. I use crashlytics for this purpose and it really helps me to fix my applications crashes. When you add this api to you application you can trace all Crashes/ANRs on a web page.
If your aim is understanding how to find reasons of ANRs from trace.txt then I have no idea. But if you need to find and fix your crashes/ANRs, then use a crash report api.
Edit: I assumed you are talking about an application which you've developed and published on google play. If you are talking about an application which is not published to google play yet, #Jeffrey Klardie's suggestion is just what you need. But it is not advised to enable Strictmode on applications at google play.
It's really hard to help on this without code to see what's going on, so instead I'll list what I would do to my own code should I be in this situation.
Run a Static Analysis tool on my code to identify some odd behavior (infinite loops, missing cases, etc.). Personally I use FindBugs.
Review the errors that pop-up from the Static Analysis tool, correct the ones that make sense for what you are doing.
Look through the code for any occurrences of "evil" code such as really long loops, synchronous activity that can be asynchronous, use of the sleep() function, asynchronous activity that is being treated synchronously, etc.
If none of the above made an impact start throwing in Log statements all over the place. Watch the output from a run and see where it gets to or what is repeating.
If none of the above worked, pop open a beer do a little yoga and then get back on the prowl and dig some more!
The most likely cause is the compiler is waiting for some interweb operation on the UI thread.
My Android app uses the AWS Java SDK for uploading user photos to S3.
Whenever a user's phone's clock is 'skewed', this causes all transfers to fail. This is a well documented aspect of S3:
http://aws.amazon.com/articles/1109?_encoding=UTF8&jiveRedirect=1#04
It appears that the upstream S3 service reports this error quite clearly:
HTTP Status Code: 403 Forbidden
Error Code: RequestTimeToo-Skewed
Description: The difference between the request time and the server's
time is too large.
However when using the Java SDK, it seems as if the informative 403 code is lost ... and I have only an opaque "TransferState.Failed" to go by (which incidentally is the same error if internet connectivity is lost, if it times out, etc...).
As far as I can tell from the docs:
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/index.html
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/TransferProgress.html
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/Transfer.TransferState.html
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/Upload.html
There is no way to get the additional "RequestTimeToo-Skewed" metadata about a transfer failure.
Am I missing it? Is there any way to get additional error information when an S3 transfer fails using Amazon's Java SDK?
UPDATE #1:
A commenter kindly highlighted that I should clarity two points:
I am actually using the AWS SDK for Android (which seems very similar to the Java SDK, but is nonetheless distinct)
I am using the TransferManager class to perform my upload. Apparently, this is a high-level class that wraps the lower-level AmazonS3Client ... and this lower-level class should expose the error reporting I need, but I am still investigating the exact tradeoffs involved between TransferManager and AmazonS3Client. As far as I can tell, there is no way to get progress information via the (synchronous) AmazonS3Client.putObjectRequest which would be a blocker for me...
UPDATE #2:
My sincere thanks to Jason (of the AWS SDK team) for stopping by and helping me out here. The important information is, indeed, available as properties on an AmazonS3Exception if you use certain methods. The docs had originally confused me and I thought that a manual Thread.sleep() loop was required to poll status (and thus I could not leverage waitForCompletion or waitForException), but if you use ProgressListener on PutObjectRequest you can get full progress callbacks and the error-fidelity of AmazonS3Exception.
these two methods should help you out:
Transfer.waitForCompletion()
Transfer.waitForException()
If you detect that your transfer has failed based on a transfer progress event, you can simply call Transfer.waitForException() to be returned the exception that occurred. That exception will be an AmazonServiceException in this case, with all of the info that you need to see that the real problem was a clock skew issue.
Alternatively, the Transfer.waitForCompletion() method will unwrap the original exception from an ExecutionException and directly throw the original exception, just as if it'd all been happening on one thread. This might be a more convenient approach if you want to use a catch blocks to catch different types of errors cleanly and elegantly.
I disagree that the "catch Exception" block is "brutally broad". The point of that code is to catch any error that happens, mark the transfer as failed and rethrow the error so that the application code can know about it. If it were less broad, then that's exactly the case where exceptions could sneak through and transfer progress wouldn't be updated correctly and would be out of sync with reality.
Give those two methods and shot and let us know if that helps!
Well, I have debugged Amazon's SDK and I'm sorry to say that this information is being swallowed internally. Perhaps I will try to submit a patch.
Details: an AmazonS3Exception is being thrown internally which does in fact accurately report this exact error scenario, but a brutally broad try catch ( Exception e ) consumes it and washes away the specificity.
Here is the guilty try-catch:
https://github.com/aws/aws-sdk-java/blob/master/src/main/java/com/amazonaws/services/s3/transfer/internal/UploadMonitor.java#L145
Here is a screenshot showing that an AmazonS3Exception is correctly thrown with the right info...
I recently noticed that I'm getting reports of the following crash in my Android Developer Console:
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
at java.net.InetAddress.getHostByAddrImpl(InetAddress.java:440)
at java.net.InetAddress.getHostName(InetAddress.java:313)
at android.media.MediaPlayer.checkHostdata(MediaPlayer.java:869)
at android.media.MediaPlayer.isLocalhost(MediaPlayer.java:940)
at android.media.MediaPlayer.setDataSourceBase(MediaPlayer.java:980)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1085)
[the rest is irrelevant]
It seems that somewhere in the MediaPlayer.setDataSource method there is some code that touches the network which is causing StrictMode to bark. Which is a bit surprising as calling setDataSource on the main thread seems to be common practice.
So my question is, what's the best way to go about dealing with this issue? Should I move the mediaPlayer out of the main thread? Should I ignore it? Or, something else?
Well, strategically, this feels like a somewhat over-aggressive bit of StrictMode logic, one that perhaps could get fixed in the future, if getHostByAddrImpl() really isn't at risk of doing a blocking network I/O call.
Tactically, you should move the setDataSource() call to a background thread, particularly when the source is pointing at the network (http, rtsp, etc.).
I know what causes a NetworkOnMainThreadException, as well as how to fix it, but for the purposes of improving the development experience, I'd like to be able to catch the exception and at least log the event or alert the user (who is still the developer at this point)...
Strangely, I'm not having any luck with this code (which sends and receives over my TCP socket):
try
{
toServer.println (msg.trim());
resp = fromServer.readLine();
}
catch (android.os.NetworkOnMainThreadException nex)
{ ... do something here ... }
Eclipse doesn't recognize that exception at all, and I copy-pasta-ed the exception type from the Android Developer website -- I'm pretty sure I spelled it right...
Is there something I don't know about Java (perhaps) that makes this exception uncatchable??
Thanks,
R.
Is there something I don't know about Java (perhaps) that makes this exception uncatchable??
Yes, StrictMode makes it uncatchable. Either way though, you should not catch this exception. Instead, you should implement your code correctly by wrapping your code in an AsyncTask. The reason why this exception is thrown is to prevent you from slowing down your application by blocking the UI thread.
Read my blog post for more info:
Why Ice Cream Sandwich Crashes Your App
Well I just tested this on my version of eclipse, and it works just fine.. I guess I would check which version of the api you are using? looks like to throw that exception you need a minimum api version 11. Otherwise perhaps eclipse is to blame? All I know is that this code is correct and should be executing without any issues.
Are you sure this is the first use of networking in your application?
If you are connecting to a server usually at that time NetworkOnMainThreadException should be thrown. Try adding a log statement before the try and see if it shows up. If it does not the Exception is thrown earlier.
I've released my second game project on the Android Market this week, and immediately had multiple 1-star reports due to force closes. I tested it on many handsets and many emulators with zero issues. I'm completely at a loss for how to proceed and looking for advice.
I use Thread.setDefaultUncaughtExceptionHandler to intercept and report uncaught exceptions, then close gracefully. The people reporting force closes aren't getting to any of that, even though it is the first thing set in the application's main task constructor, and everything is wrapped in try/catches throughout. They are also reporting that there is no "Send Report" option in the force close popup (providing the Developer Console error reports), so I have absolutely no way of knowing what the problem is.
Uses Android 2.0, with android:minSdkVersion="5". Only Permission required is INTERNET.
(on Android market as 'Fortunes of War FREE' if you want to test)
I'm a bit surprised about the missing "Send report" button. What API level did you build the game with? I usually build the level with your minimum API level to make sure you're not using any API calls beyond that, but then switch back to the highest API level so you can use functionality like "install to SD".
I'm sure there's at least one user who wrote you a mail. Can you ask them to install LogCollector and mail you the log?
Btw, in general, I wouldn't use Thread.setDefaultUncaughtExceptionHandler so there IS the option to send a report. (It's ominously missing in your case, but normally, it should be there.)
Btw btw, the exception handler applies to the current thread. If you have an OpenGL app, maybe the crash happens in the GL thread?
I'm not sure if I understood you correctly, but as far as I know Android only shows that report dialog if you use its default UncaughtExceptionHandler.
Try this:
In your UncaughtExceptionHander's constructor, call Thread.getDefaultUncaughtExceptionHandler and save the returned object in a variable (let's call it defaultHandler). In your Handler's uncaughtException() do the things you want to do, and then call defaultHandler.uncaughtException() afterwards.
Maybe something you should know:
In my experience, your Context isn't functional anymore at uncaughtException(). So, you can't send broadcasts, etc anymore.
By the way, if you really wrapped everything in try/catch, that could be the reason why error reporting doesn't work as expected? :P
Good luck
Tom
Perhaps the force closes are caused by stalls, rather than exceptions. Users may not notice the difference. This kind of problem can occur more often if users have CPU hogging services running at the same time as your application, which explains why you're not seeing the issue in your testing.
Permission Internet sounds a lot like you try to transfer data from the net, which is very fast in your local LAN, but all of a sudden becomes slow (and time consuming) when people try this over their GSM connections.
If you then do the data transfer in the UI thread, this one is blocked and the system detects the block - but then this should end up in a "Did not respond" -- but then I've seen one user report an error with in the market on my app that was such a slow down cause.