SIGSEGV error with QtThread on deleting QSGNode - android

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.

Related

Kotlin in Flutter application causing Crash

Since the last flutter update there has been an issue when I try to use the media player plugin witch uses Kotlin.
When you hit the button and it is suppose to play the audio file, it causes the application to crash.
fun play(url: String) {
player.reset()
channel.invokeMethod("onPosition", 0.0)
player.setDataSource(url)
player.prepareAsync()
channel.invokeMethod("onIsLoading", null)
task?.cancel()
task = object : TimerTask() {
override fun run() {
if (player.isPlaying) {
session.setPlaybackState(PlaybackStateCompat.Builder()
.setState(PlaybackStateCompat.STATE_PLAYING, player.currentPosition.toLong(), 1f)
.build())
channel.invokeMethod("onPosition", player.currentPosition.toDouble() / player.duration.toDouble())
}
}
}
timer.schedule(task, 0, 100)
}
it was suggested that I add this in.
activity.runOnUiThread(java.lang.Runnable {
channel.invokeMethod(...)
})
but I if I do I get
Unresolved Reference: activity
This is the error message.
java.lang.RuntimeException: Methods marked with #UiThread must be executed on the main thread. Current thread: Timer-0
at io.flutter.embedding.engine.FlutterJNI.ensureRunningOnMainThread(FlutterJNI.java:605)
at io.flutter.embedding.engine.FlutterJNI.dispatchPlatformMessage(FlutterJNI.java:515)
at io.flutter.embedding.engine.dart.DartMessenger.send(DartMessenger.java:76)
at io.flutter.embedding.engine.dart.DartExecutor.send(DartExecutor.java:166)
at io.flutter.view.FlutterNativeView.send(FlutterNativeView.java:155)
at io.flutter.plugin.common.MethodChannel.invokeMethod(MethodChannel.java:98)
at io.flutter.plugin.common.MethodChannel.invokeMethod(MethodChannel.java:84)
at live.exit.musicplayer.MusicPlayer$play$1.run(MusicPlayer.kt:49)
at java.util.TimerThread.mainLoop(Timer.java:562)
at java.util.TimerThread.run(Timer.java:512)
I am at a bit of a loss, this is suppose to be playing audio.
I know NOTHING about kotlin.
I think you're using ragotrebor music-player plugin (https://gitlab.com/ragotrebor). Looking at their history a merge was made about a month ago which should fix this issue.
Just update to the latest version of the plugin and you should be good to go!
Background
It's related to a change in flutter to fix a bug which caused FlutterJNI (Java Native Interface) to crash intermittently when certain methods were executed outside of the main thread. Flutter was changed to thrown an exception in all cases, to avoid this intermittent crash and force developers to run methods correctly on the UI thread. Unfortunately this caused many existing plugins to crash and developers were required to update their source code.
Reference links
Change with discussion: https://github.com/flutter/engine/commit/2c9e37c34e79475bbde7c8163eb5e56cdb9662a
Found through this thread discussing a fix for a specific plugin: https://github.com/flutter/flutter/issues/34993).
Merge request details for music player plugin that fixed this issue: https://gitlab.com/exitlive/music-player/commit/693131a7f0d29b3ee42ba9fa2a5ce65aef7652fb

Android - JNI / NDK - crash with SIGSEV - signal handling not triggered

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.

Can't execute JavaVM->DetachCurrentThread(): "attempting to detach while still running code"

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."

Apache Mina: IllegalStateException when calling connect

I am trying to make a simple message application on Android with Apache Mina. I am getting IllegalStateException when calling connect(new InetSocketAddress(HOSTNAME, PORT)).
Here is my client code:
http://pastebin.com/NR2H6X0t
Here is my server code:
http://pastebin.com/Q5fQnu2p
And here is the logcat output:
http://pastebin.com/Egsh0Ce4
I am testing my apllications in same wifi network with a tablet and phone.
Even I can't see anything wrong with your code. But the LogCat says org.apache.mina.transport.socket.nio.NioSocketConnector.connect() of NioSocketConnector.java class at line# 185) your application is throwing NetworkOnMainThreadException. First fix that than check if you are getting the same error.
Apart from above I have a suggestion (for readability purpose): In connectToServerButtonClicked() of ClientActivity instead of using
for (; ; ) {
//rest of your code
}
better use
while(true){
//rest of your code
}
Edited: On request of #alkis coping my answer from comment below to answer part for better redability
NetworkOnMainThreadException : This exception is thrown when an application attempts to perform a networking operation on its main thread. Run your network related code in AsyncTask.

Error calling method on NPObject! in Android 2.2

I'm using addJavascriptInterface within my Android application to allow JavaScript to invoke functions I've created in my native Java application.
This worked well in Android 2.1, however in Android 2.2 I receive the error message "Error calling method on NPObject!"
When I instrument the method call the internals of the native method are getting called, however the exception is being throw in JavaScript.
I was getting this exact error:
Uncaught Error: Error calling method on NPObject!
Turns out I was attempting to invoke a JavascriptInterface function from a webview like so:
AndroidJS.populateField(field);
and on the Java side, the function didn't accept a parameter:
public void populateField() {}
Simply allowing the Java function to accept a parameter solved this error for me.
E.g.,
public void populateField(String field) {}
This may not be, and probably is not, the only reason this error could be thrown. This is simply how I resolved my specific scenario. Hope this helps! :)
OK, I have same problem as well, just in today.
What I did is putting code in UI Thread, like code below :
/**
* 給網頁Javascript呼叫的method
* Method for Javascript in HTML
* #param java.lang.String - Playlist ID
*/
public int callListByPID(final String pId)
{
Log.i(Constants.TAG, "PAD Playlist ID from HTML: "+pId);
runOnUiThread(new Runnable()
{
public void run()
{
// Put your code here...
}
});
return 1;
}
This solved my problem, and hope it can help some body... :-)
In my experience this problem is caused by Javascript interfaces bringing back objects that Javascript doesn't automatically identify.
In Android this is caused by wrappers like Boolean or Long in comparison to their native versions boolean and long.
//This will fail
public Long getmyLongVal() {
return 123456789;
}
//This will work
public long getMyNativeLongVal() {
return 123456789;
}
So remove your wrapper classes to any methods being used by Javascript if you want to avoid NPObject errors.
Here's a twist I found on this problem that could be useful for some of the folks running into this problem (and it likely explains intermittent failures that seem to defy explanation)...
If any exceptions are thrown (and not caught) in the return handler code prior to allowing the javascript interface callback to return clean, it will propagate back as a failed call and you will also get this error - and it would have nothing to do with missing functions or parameters.
The easiest way to find this case (whether or not you use this in your final implementation) is to push whatever handler code you have back onto the UI thread (the callback will not be on the UI thread) - this will allow the callback to return clean and any subsequent exceptions that occur will propagate properly up until you catch them or until the app crashes. Either way you will see exactly what is really happening. Otherwise the uncaught exception passes back to javascript where it will not be handled or reported in any way (unless you specifically built error trapping code into the JS you were executing).
Good Luck All.
bh
I had the same problem with Javascript-to-Java interface (WebView.addJavascriptInterface).
In Android 2.1 everything worked just fine but in Android 2.2 Javascript failed to call methods from this interface. It returned an error: Uncaught Error: Error calling method on NPObject!
It seems that on Android 2.2, the WebView has problem with Boolean data type returned from interface functions.
Changing:
public Boolean test_func() { return true; }
... to:
public int test_func() { return 1; }
... solved the problem.
This I believe is no longer supported anymore ( Always game NPObject error ) .
Please refer to the answer in this thread
Visit open an activity from a CordovaPlugin

Categories

Resources