Sharing a JavaVM* across threads in Android NDK - multithreading

I want to call Java class methods from a cpp file that receives call backs from another executable.
To achieve this, I have retrieved a JavaVM pointer using the android::AndroidRuntime::getJavaVM() method in the .cpp file that directly receives JNI method calls. I am sharing this JavaVM pointer via the constructor to the eventual .cpp file where I call required Java methods as follows:
/* All the required objects(JNIEnv*,jclass,jmethodID,etc) are appropriately declared. */
**JNIEnv* env;
jvm->AttachCurrentThread(&env, NULL);
clazz = env->FindClass("com/skype/ref/NativeCodeCaller");
readFromAudioRecord = env->GetStaticMethodID(clazz, "readFromAudioRecord", "([B)I");
writeToAudioTrack = env->GetStaticMethodID(clazz, "writeToAudioTrack", "([B)I");**
However, I get a SIGSEGV fault running this code.
According to the JNI documentation this seems to be the appropriate way to obtain JNIEnv in arbitary contexts: http://java.sun.com/docs/books/jni/html/other.html#26206
Any help in this regard will be appreciated.
Regards,
Neeraj

Global references will NOT prevent a segmentation fault in a new thread if you try to use a JNIEnv or JavaVM reference without attaching the thread to the VM. You were doing it properly the first time around, Mārtiņš Možeiko is mistaken in implying that there was something wrong with what you were doing.
Don't remove it, just learn how to use it. That guy doesn't know what he's talking about, if it's in jni.h you can be pretty sure it's not going anywhere. The reason it's not documented is probably because it's ridiculously self explanatory. You don't need to create GlobalReference objects or anything either, just do something like this:
#include <jni.h>
#include <string.h>
#include <stdio.h>
#include <android/log.h>
#include <linux/threads.h>
#include <pthread.h>
#define LOG_TAG "[NDK]"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
static pthread_mutex_t thread_mutex;
static pthread_t thread;
static JNIEnv* jniENV;
void *threadLoop()
{
int exiting;
JavaVM* jvm;
int gotVM = (*jniENV)->GetJavaVM(jniENV,&jvm);
LOGI("Got JVM: %s", (gotVM ? "false" : "true") );
jclass javaClass;
jmethodID javaMethodId;
int attached = (*jvm)->AttachCurrentThread(jvm, &jniENV,NULL);
if(attached>0)
{
LOGE("Failed to attach thread to JavaVM");
exiting = 1;
}
else{
javaClass= (*jniENV)->FindClass(jniENV, "com/justinbuser/nativecore/NativeThread");
javaMethodId= (*jniENV)->GetStaticMethodID(jniENV, javaClass, "javaMethodName", "()V");
}
while(!exiting)
{
pthread_mutex_lock(&thread_mutex);
(*jniENV)->CallStaticVoidMethod(jniENV, javaClass, javaMethodId);
pthread_mutex_unlock(&thread_mutex);
}
LOGE("Thread Loop Exiting");
void* retval;
pthread_exit(retval);
return retval;
}
void start_thread(){
if(thread < 1)
{
if(pthread_mutex_init(&thread_mutex, NULL) != 0)
{
LOGE( "Error initing mutex" );
}
if(pthread_create(&thread, NULL, threadLoop, NULL) == 0)
{
LOGI( "Started thread#: %d", thread);
if(pthread_detach(thread)!=0)
{
LOGE( "Error detaching thread" );
}
}
else
{
LOGE( "Error starting thread" );
}
}
}
JNIEXPORT void JNICALL
Java_com_justinbuser_nativecore_NativeMethods_startThread(JNIEnv * env, jobject this){
jniENV = env;
start_thread();
}

Solved the problem. The segmentation fault was because I could not retrieve a jclass object from the JNIEnv object retrieved from the shared jvm pointer.
I propogated a Global reference jclass object alongwith the jvm and the problem was solved.
Thanks for your help Mārtiņš Možeiko!..
Regards,
Neeraj

Related

Posix Threads with Mutex

I have started working on POSIX threads. I wrote a simple code.
My question is on Mutex.
Initializing the mutex inside threaded function gives wrong result. While initializing the mutex inside main function (before creation of threads) gives proper result. Why is that happening?
The count value is expected to be 200000 but it is showing some improper value < 200000.
Here is my code.
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <malloc.h>
void *thread_handler (void *name);
unsigned long int count=0;
pthread_mutex_t lock;
void main () {
pthread_t thread_num[2];
pthread_attr_t attr;
pthread_attr_init (&attr);
int i;
for (i=0;i<2;i++) {
if (pthread_create (&thread_num[i],&attr,(void *) thread_handler,NULL)<0) {
printf ("\n Error in Creating the Threads");
}
}
for (i=0;i<2;i++) {
pthread_join(thread_num[i],NULL); //Waiting for the Thread to Exit
}
printf ("\n The value of count=%ld\n",count);
}
void *thread_handler (void *arg) {
int i;
if (pthread_mutex_init (&lock,NULL)!=0) {
printf ("\n Error in Initializing the Mutex");
}
pthread_mutex_lock (&lock);
for (i=0;i<100000;i++) {
count++;
}
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
Thanks in Advance,
NDPrasad.
When you initialize the mutex inside the thread_handler function, it is initialized twice(because you create two threads that execute this function). It causes undefined behavior(which means that anything can happen).
A quote from here:
Attempting to initialize an already initialized mutex results in undefined behavior.

Runtime check failure in CString destructor caused by setting Class ptr to NULL?

so somewhere along the lines of putting this app together I've started to get a runtime check failure stack corruption when the destructor for a cstring class member is called.
I've gotten to the point of trying to debug this by throwing bricks at the issue but still havent root caused it. At the current moment the class that the cstring resides in does nothing but initialize its private string members and set a pointer to another class to NULL.
Interestingly if I do not set the class pointer to NULL and comment out that line the corruption goes away. I think this is somewhat of a red herring, and that something is changing in the way the compiler is putting the code together when it pulls in the .h file that contains theCLog definitions and that would be used since I'm declaring a pointer to that object.
int _tmain(int argc, _TCHAR* argv[])
{
DWORD a = 0xBABA; //just to help catch the corrupter
DWORD b = 0xDFDF;
CStringW startat = L"\\\\anetworkshare\\fre";
CStringW lookfor = L".inf";
DirEnum myEnum(startat,lookfor);
ULONG en = a + b;
en = a - b;
return 0;
}
DirEnum.cpp
DirEnum::DirEnum(CString startingdir,CString fileFilter)
{
m_plogfile = NULL; //If you comment out this line corruption goes away
m_startingdir = L"";
m_extfilter = L"";
if(startingdir.GetLength() > 0)
m_startingdir = startingdir;
if(fileFilter.GetLength() > 0)
m_extfilter = fileFilter;
//following commented out to tshoot
//CLogBase& ref = ref.GetInstance();
//logBase = &ref;
//m_plogfile = new CLog(L"DirEnumerator",L"logfile.txt",logINFO);
}
Now I suspect that something in the log.h file is causing a change to occuur in the ATL or CString libraries but I dont know what. Heres the log.h file
#pragma once
//#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
using namespace std;
#ifndef TYPEDEF_H
#define TYPEDEF_H
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <tchar.h>
#include <time.h>
//simple defines to allow the TCHAR library to be used
typedef std::basic_string<TCHAR> tstring;
typedef std::basic_ostream<TCHAR> tostream;
typedef std::basic_istream<TCHAR> tistream;
typedef std::basic_ostringstream<TCHAR> tostringstream;
typedef std::basic_istringstream<TCHAR> tistringstream;
typedef std::basic_ofstream<TCHAR> tofstream;
#if defined(UNICODE) || defined(_UNICODE)
#define tcout std::wcout
#define tcin std::wcin
#else
#define tcout std::cout
#define tcin std::cin;
#endif
#endif
#if defined DEBUG || defined (_DEBUG)
#define TOCONSOLE
#endif
typedef enum LOGLVL{logERROR =0,logWARN,logINFO,logDEBUG};
//CLogBase os a singleton log class. Intent is that you can establish a reference from anywhere in the project and write to the same file
// without having locking issues or threading issues
class CLogBase
{
public:
static CLogBase& GetInstance(CString logname = L"log.txt",LOGLVL lvl = logWARN);
~CLogBase(void);
tostringstream& GetLog(LOGLVL level);
tostringstream& GetStream(LOGLVL);
void Forceflush();
private:
CLogBase(CString file,LOGLVL lvl);
//our outstream
tostringstream m_os;
tostringstream m_dummy;
tofstream m_filestream;
CString m_filename;
LOGLVL m_reportlvl;
//Private declarations to prevent copy constructors from being invoked; these are do nothig implimentations
CLogBase(CLogBase const&);
void operator=(CLogBase const&);
};
class CLog
{
public:
CLog(CString component);
CLog(CString component,CString logname,LOGLVL lvl);
~CLog();
void Log(LOGLVL,CString message);
void CLog::Flush();
tostringstream& CLog::GetStream(LOGLVL lvl);
private:
CString m_componentname;
CLogBase* m_logBase;
};
I thought I would answer this as I found the issue. this was not a coding problem per se but a visual studio issue.
What happened was that I was storing the direnum.h file and .cpp file in a different directory than the one used for the main project. referencing the header with #include "..\somedir\direnum.h"
at one point in time visual studio reported the file as locked and did I want to overwrite \ cancel etc. I choose overwrite but what seemed to happen was that this caused VS to COPY the files to the current project. All my troubleshooting attempts were being edited in the local somename.h file whtne opened in the editor but the compiler was doing the correct thing and pulling down the .h file from the location above.
removing switching to the now local copy of direnum.h and recompiling fixed this as it was compiling part of the code as ANSI and the other part as WCHAR

Qt GUI user interaction with QMessageBox from within QThread object

I'm using QThread with MyObject->moveToThread(myThread); for communication functions that take a while. A few Signals and Slots keep the GUI posted about the progress.
Howeever, some situation may occur during the threaded communication that requires user interaction - since a QMessageBox can't be created inside a thread, I was thinking to emit a signal that would allow me to pause the thread and show the dialog. But first of all, there does not seem to be a way to pause a thread, and second, this attempt probably fails because it requires a way to pass a parameter back to the thread when resuming it.
A differenet approach might be to pass all parameters in question to the thread beforehand, but this may not alway be an option.
How is this usually done?
Edit
Thanks for the comment #1 and getting my hopes up, but please elaborate on how to create e.g. a dialog from an object within a thread and how to pause it..
The following example code with Qt 4.8.1 and MSVC++ 2010 results in:
MyClass::MyClass created
MainWindow::MainWindow thread started
MyClass::start run
ASSERT failure in QWidget: "Widgets must be created in the GUI thread.", file kernel\qwidget.cpp, line 1299
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myclass.h"
#include <QThread>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QThread *thread = new QThread();
MyClass* myObject = new MyClass();
myObject->moveToThread( thread );
connect(thread, SIGNAL( started()), myObject, SLOT(start()));
connect(myObject, SIGNAL( finished()), thread, SLOT(quit()));
connect(myObject, SIGNAL( finished()), myObject, SLOT(deleteLater()));
connect(thread, SIGNAL( finished()), thread, SLOT(deleteLater()));
thread->start();
if( thread->isRunning() )
{
qDebug() << __FUNCTION__ << "thread started";
}
}
MainWindow::~MainWindow()
{
delete ui;
}
myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = 0);
signals:
void finished();
public slots:
void start();
};
#endif // MYCLASS_H
myclass.cpp
#include "myclass.h"
#include <QMessageBox>
#include <QDebug>
MyClass::MyClass(QObject *parent) :
QObject(parent)
{
qDebug() << __FUNCTION__ << "created";
}
void MyClass::start()
{
qDebug() << __FUNCTION__ << "run";
// do stuff ...
// get information from user (blocking)
QMessageBox *msgBox = new QMessageBox();
msgBox->setWindowTitle( tr("WindowTitle") );
msgBox->setText( tr("Text") );
msgBox->setInformativeText( tr("InformativeText") );
msgBox->setStandardButtons( QMessageBox::Ok | QMessageBox::Cancel);
msgBox->setDefaultButton( QMessageBox::Ok);
msgBox->setEscapeButton( QMessageBox::Cancel);
msgBox->setIcon( QMessageBox::Information);
int ret = msgBox->exec();
// continue doing stuff (based on user input) ...
switch (ret)
{
case QMessageBox::Ok:
break;
case QMessageBox::Cancel:
break;
default:
break;
}
// do even more stuff
emit finished();
}
Use Qt::BlockingQueuedConnection in a signal/slot connection (the call to QObject::connect()).
http://doc.qt.digia.com/qt/qt.html#ConnectionType-enum
This will block your thread until the slot on the UI thread returns, the slot in the UI thread is then free to display a messagebox/modal dialog/whatever you want to do.
You must be sure that your worker thread is actually not on the UI thread, because as the docs say this will cause a dead lock if the signal and slot are on the same thread (since it will block itself).
I can't give any specific code right now, but I would do it like this:
In MyClass::start() lock a QMutex.
Emit a signal e.g. messageBoxRequired().
Wait on a shared QWaitCondition on the recent mutex. This will also unlock the mutex while the thread is waiting.
In a slot in your MainWindow, e.g. showMessageBox(), show the message box.
Store the returned value in a member of MyClass. You can do this by offering a setter and getter which use the mutex in order to protect the member. Obviously MyClass itself should only access that member with those setters/getters itself. (Also see QMutexLocker for that).
Call wakeOne() or wakeAll() on the shared QWaitCondition.
The previous wait() call will return and MyClass::start() will continue execution. If I understand the docs correctly, QWaitCondition will lock the mutex again before it returns from wait(). This means you have to unlock the mutex directly after the wait() call.
You can access the message box's return value from your class member (using a thread-safe getter)
Implementations for thread-safe setters/getters would be as follows:
void MyClass::setVariable( int value )
{
QMutexLocker( &_mutex );
_value = value;
}
int MyClass::getVariable() // Not sure if a 'const' modifier would work here
{
QMutexLocker( &_mutex );
return _value;
}

error C2064: term does not evaluate to a function taking 0 arguments thread.hpp(60)

I'm creating c++ game server. The server creates many objects monster, and every monster should have its thread with specific function.
I get error :
error C2064: term does not evaluate to a function taking 0 arguments
thread.hpp(60) : while compiling class template member function 'void
boost::detail::thread_data<F>::run(void)'
monster.cpp:
#include "monster.h"
monster::monster(string temp_mob_name)
{
//New login monster
mob_name = temp_mob_name;
x=rand() % 1000;
y=rand() % 1000;
boost::thread make_thread(&monster::mob_engine);
}
monster::~monster()
{
//Destructor
}
void monster::mob_engine()
{
while(true)
{
Sleep(100);
cout<< "Monster name"<<mob_name<<endl;
}
}
monster.h:
#ifndef _H_MONSTER_
#define _H_MONSTER_
//Additional include dependancies
#include <iostream>
#include <string>
#include "boost/thread.hpp"
using namespace std;
class monster
{
public:
//Functions
monster(string temp_mob_name);
~monster();
//Custom defined functions
void mob_engine();
int x;
int y;
};
//Include protection
#endif
mob_engine is a non-static member function, so it has an implicit this argument.
Try this:
boost::thread make_thread(boost::bind(&monster::mob_engine, this));
According to this similar question boost:thread - compiler error you can even avoid using bind by simply writing:
boost::thread make_thread(&monster::mob_engine, this);
Also, you will probably want to declare a boost::thread member variable to keep a reference to the thread.

Try...catch causes segmentation fault on embedded ARM with posix threads

Today, I posted a problem about a segmentation fault after destruction of a std::string (see this post). I've stripped the code so that I don't use the STL and still have a segmentation fault sometimes.
The following code works just fine on my PC running Linux. But using the ARM crosscompiler suppplied by the manufactor of our embedded device, it gives a segmentation fault just before catch (...).
This problems seems to have a link with this post in Google Groups, but I haven't found any solution yet.
The code is compiled using an ARM cross compiler
Any suggestions are still welcome!
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *ExecuteThreadMethod(void *AThread);
class Thread
{
private:
pthread_t internalThread;
public:
void RunSigSegv()
{
try
{
for (int i = 0; i < 200; i++)
{
usleep(10000);
}
} // <---- Segmentation fault occurs here
catch(...)
{
}
}
void Start()
{
pthread_attr_t _attr;
pthread_attr_init(&_attr);
pthread_attr_setdetachstate(&_attr, PTHREAD_CREATE_DETACHED);
pthread_create (&internalThread, &_attr, ExecuteThreadMethod, this);
}
};
void *ExecuteThreadMethod(void *AThread)
{
((Thread *)AThread)->RunSigSegv();
pthread_exit(NULL);
}
Thread _thread1;
Thread _thread2;
Thread _thread3;
Thread _thread4;
void s()
{
_thread1.Start();
_thread2.Start();
_thread3.Start();
_thread4.Start();
}
int main(void)
{
s();
usleep(5000000);
}
I once encountered a problem like this which was caused by linking with a version of libstdc++ with no threading support, meaning that all threads shared a common exception handling stack with disastrous consequences.
Make sure the cross-compiler and its libraries were configured with --enable-threads=posix.
Just a diagnostic question: What happens if you don't detach the thread in Start()? You'd have to pthread_join() the threads back in main().
Also, have you considered Boost's threads? That might be more appropriate since you're using C++ rather than C.

Resources