I have Android native C++ code. However, sometimes when I send app to background and back, it crash with SIGSEGV. I want to debug it using my own signal handling and print stack trace, however, when this error occurs, my signal handling is not triggered at all.
To JNI_OnLoad method, I have added:
struct sigaction sighandler;
memset (&sighandler, '\0', sizeof(sighandler));
sighandler.sa_sigaction = &android_sigaction;
sighandler.sa_flags = SA_SIGINFO;
int watched_signals[] = { SIGABRT, SIGILL, SIGSEGV, SIGINT, SIGKILL };
for(int signal : watched_signals)
{
sigaction(signal, &sighandler, &old_sa[signal]);
}
And I have:
static struct sigaction old_sa[NSIG];
static void android_sigaction(int signal, siginfo_t *siginfo, void *context)
{
MY_LOG("Sending PID: %ld, UID: %ld\n", (long)siginfo->si_pid, (long)siginfo->si_uid);
old_sa[signal].sa_handler(signal);
}
However, android_sigaction is never trigerred for the error, when app goes from background. I have tried to create bug in code (writing outside array bounds), trigger it with button push and the callback is correctly called.
What is going on?
Assuming that you're using Android 5.0+ device, your problem may be caused by ART. It exposes own signal() and sigaction() so it has a chance to steal signal and pass it somewhere else.
For debugging purposes you could try direct syscall:
for(int signal : watched_signals)
{
syscall(_NR_sigaction, signal, &sighandler, &old_sa[signal]);
}
So now your handler goes directly to kernel and ART shouldn't change it.
Of course it is OK only for debugging. If you want to go with this for a prod - you need to develop some logic that will respect previous handler.
P.S. also checking returned value and errno is a good idea as well.
Related
I am working on a Qt app which runs on android & iOS.
Scenario:
Calling delete on a pointer causes my app to crash sometimes gives me the following error on Android.
Fatal signal 11 (SIGSEGV), code 1, fault addr 0x3c in tid 7134 (QtThread)
This is caused due to a delete call in updatePaintNode of my QQuickItem derived class.
// My updatePaintNode logic relevant to this question
QSGNode * MyQQuickItem::updatePaintNode(QSGNode * oldNode, UpdatePaintNodeData * updatePaintNodeData) {
Q_UNUSED(oldNode)
Q_UNUSED(updatePaintNodeData)
if(class_mem_node != Q_NULLPTR) {
delete class_mem_node; // this is where the crash occurs
}
class_mem_node = new QSGNode;
// Execute drawing logic
return class_mem_node;
}
Problem:
Another window of my application is dependent on MyQQuickItem::updatePaintNode to execute but sometimes on Android the call to delete class_mem_node causes the crash with the Fatal signal error. Interestingly, the issue only happens on android, not on iOS or OSX.
Question:
What is wrong in my logic in updatePaintNode ? Is this a thread synchronisation issue?
Is there some way I can check whether the QSGNode is in use & return out?
When you return class_mem_node; you don't have ownership of the class_mem_node any more.
The implementation may delete the node when it becomes not useful. It then passes nullptr as oldNode on the next call to the updatePaintNode().
Don't store class_mem_node, use oldNode.
I'm working on an application with Xamarin (in Visual studio 2015) for android.
When I run my application in debug mode, sometime the application stop with message "MyApplication has stopped".
I've added this code in MainActivity :
// Catch Exception
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironment_UnhandledExceptionRaiser;
I added breakpoints add log in both functions, but I see no traces in log and the breakpoints are not reached.
How can I debug this kind of problem ?
You need to debug your application through a persistent logger i.e. adb logcat. Sadly registering an unhandled exception handler does not guarantee it will be a "catch-all" as it might never reach that point. So you will need a combination of both adb logcat and Console.WriteLine for these types of issues. Please take the following note into account when you want to see what's going on within this handler, but also make use of adb logcat to see the reason of the crash in the first place.
/// <summary>
/// When app-wide unhandled exceptions are hit, this will handle them. Be aware however, that typically
/// android will be destroying the process, so there's not a lot you can do on the android side of things,
/// but your xamarin code should still be able to work. so if you have a custom err logging manager or
/// something, you can call that here. You _won't_ be able to call Android.Util.Log, because Dalvik
/// will destroy the java side of the process.
/// </summary>
protected void HandleUnhandledException (object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception) args.ExceptionObject;
// log won't be available, because dalvik is destroying the process
//Log.Debug (logTag, "MyHandler caught : " + e.Message);
// instead, your err handling code shoudl be run:
Console.WriteLine ("========= MyHandler caught : " + e.Message);
}
https://github.com/xamarin/monodroid-samples/blob/fb9d4ed266bdf68bb1f9fa9933130b285712ec82/AdvancedAppLifecycleDemos/HandlingCrashes/App.cs
Try it: Disabled "Use Shared Runtime" in Android build options. If it not helped try - disable "Use fast deplayment".
As we all know android doesn't unload *.so after close application. I had found the solve by adding "exit(0)" at the end, that is solved problem, but I wanna know exactly that all are OK.
The code is work fine as expected after solving the problem:
static int value = 0;
// In android_main
LOGI("value = %d", value); // always print 0, but not 1 after second run of
// application as it was without "exit(0)" at the end
value = 1;
I wanna to test that on class like:
class A {
A() {
LOGI("Constructor");
}
~A() {
LOGI("Destructor");
}
statis A a;
In such way prints only "Constructor".
Maybe because of destructor is calling after when LOGI isn't working more for application that will be closed ?
Question: why LOGI in destructor isn't working? According to first example on top destructor is calling really.
This is not only pointless, but quite possibly counterproductive. If android wants the memory utilized by your process, it will terminate the process to reclaim it; if it doesn't, it won't.
To specifically address your question, killing or exiting a process does not invoke destructors, it merely terminates execution and the kernel bulk-releases all memory and (conventional) resources.
Do not try to second guess the system, as that can frequently result in killing a process only to have android immediately restart it. Further, it can allegedly cause problems with a few Android IPC resources (like the camera) which may not be freed up when the process of a utilizing application unexpectedly dies.
I have an Android app that uses NDK - a regular Android Java app with regular UI and C++ core. There are places in the core where I need to call Java methods, which means I need a JNIEnv* for that thread, which in turn means that I need to call JavaVM->AttachCurrentThread() to get the valid env.
Previously, was just doing AttachCurrentThread and didn't bother to detach at all. It worked fine in Dalvik, but ART aborts the application as soon as a thread that has called AttachCurrentThread exits without calling DetachCurrentThread. So I've read the JNI reference, and indeed it says that I must call DetachCurrentThread. But when I do that, ART aborts the app with the following message:
attempting to detach while still running code
What's the problem here, and how to call DetachCurrentThread properly?
Dalvik will also abort if the thread exits without detaching. This is implemented through a pthread key -- see threadExitCheck() in Thread.cpp.
A thread may not detach unless its call stack is empty. The reasoning behind this is to ensure that any resources like monitor locks (i.e. synchronized statements) are properly released as the stack unwinds.
The second and subsequent attach calls are, as defined by the spec, low-cost no-ops. There's no reference counting, so detach always detaches, no matter how many attaches have happened. One solution is to add your own reference-counted wrapper.
Another approach is to attach and detach every time. This is used by the app framework on certain callbacks. This wasn't so much a deliberate choice as a side-effect of wrapping Java sources around code developed primarily in C++, and trying to shoe-horn the functionality in. If you look at SurfaceTexture.cpp, particularly JNISurfaceTextureContext::onFrameAvailable(), you can see that when SurfaceTexture needs to invoke a Java-language callback function, it will attach the thread, invoke the callback, and then if the thread was just attached it will immediately detach it. The "needsDetach" flag is set by calling GetEnv to see if the thread was previously attached.
This isn't a great thing performance-wise, as each attach needs to allocate a Thread object and do some internal VM housekeeping, but it does yield the correct behavior.
I'll try a direct and practical approach (with sample code, without use of classes) answering this question for the occasional developer that came up with this error in android, in cases where they had it working and after a OS or framework update (Qt?) it started to give problems with that error and message.
JNIEXPORT void Java_com_package_class_function(JNIEnv* env.... {
JavaVM* jvm;
env->GetJavaVM(&jvm);
JNIEnv* myNewEnv; // as the code to run might be in a different thread (connections to signals for example) we will have a 'new one'
JavaVMAttachArgs jvmArgs;
jvmArgs.version = JNI_VERSION_1_6;
int attachedHere = 0; // know if detaching at the end is necessary
jint res = jvm->GetEnv((void**)&myNewEnv, JNI_VERSION_1_6); // checks if current env needs attaching or it is already attached
if (JNI_EDETACHED == res) {
// Supported but not attached yet, needs to call AttachCurrentThread
res = jvm->AttachCurrentThread(reinterpret_cast<JNIEnv **>(&myNewEnv), &jvmArgs);
if (JNI_OK == res) {
attachedHere = 1;
} else {
// Failed to attach, cancel
return;
}
} else if (JNI_OK == res) {
// Current thread already attached, do not attach 'again' (just to save the attachedHere flag)
// We make sure to keep attachedHere = 0
} else {
// JNI_EVERSION, specified version is not supported cancel this..
return;
}
// Execute code using myNewEnv
// ...
if (attachedHere) { // Key check
jvm->DetachCurrentThread(); // Done only when attachment was done here
}
}
Everything made sense after seeing the The Invocation API docs for GetEnv:
RETURNS:
If the current thread is not attached to the VM, sets *env to NULL, and returns JNI_EDETACHED. If the specified version is not supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise, sets *env to the appropriate interface, and returns JNI_OK.
Credits to:
- This question Getting error "attempting to detach while still running code" when calling JavaVm->DetachCurrentThread that in its example made it clear that it was necessary to double check every time (even though before calling detach it doesn't do it).
- #Michael that in this question comments he notes it clearly about not calling detach.
- What #fadden said: "There's no reference counting, so detach always detaches, no matter how many attaches have happened."
I have created a simple program that reproduces the problem. When I lock the phone, or if I switch to another application in my android phone, the worker thread continues printing, but the event loop stops. When I switch back to my application, the event-loop resumes.
If I replace QGuiApplication with QCoreApplication, the problem disappears. If I compile with Qt 5.2 instead of Qt 5.3, the problem disappears. Qt 5.4 has the same problem as Qt 5.3.
static int count = 0;
void workerThread()
{
while (1) {
qDebug("Worker thread %d", count++);
sleep(1);
}
}
void MyObject::step()
{
qDebug("Event loop %d", count++);
}
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
MyObject w;
QTimer timer;
QObject::connect(&timer, SIGNAL(timeout()), &w, SLOT(step()));
timer.start(1000);
QtConcurrent::run(workerThread);
return a.exec();
}
How do I prevent QGuiApplication from stopping the event loop when the app loses focus? I need my app to process events even when not in the foreground.
As mentioned in my comments, I created a bugreport for you with the risk of being rejected, but at least we would get feedback from the official maintainers.
QGuiApplication "stops" when locking the phone or switching application.
It has now been withdrawn, which is fair enough, because as the maintainer claims, you should focus on creating a service rather than activity. There is no dedicated Qt API for that just yet, however.
The reason why it is not good idea to this in an activity is simply that the application may be killed, even instantly, when it gets into the "background. Also, it may drain battery earlier than the user may expect it to. In short, this is considered as a bug rather than a feature in 5.2 by the maintainer(s) which seems to have been fixed.
Here you can find some help how to create a service as of today:
Build background service with Qt on android