For some reason, when I try to access a java object (which persists throughout the entire program, BTW) from a thread, the program crashes. Here's a boiled down example to demonstrate the problem:
#include <jni.h>
#include <pthread.h>
pthread_t thread;
jobject object;
JavaVM* jvm;
/*
Our thread function:
*/
void* run( void* );
extern "C" void Java_com_Program_Initialize( JNIEnv* jnv, jobject caller )
{
object = caller;
jnv->GetJavaVM( &jvm );
/*
Before launching our thread, this works just fine:
*/
jnv->CallVoidMethod( object, jnv->GetMethodID( jnv->GetObjectClass( object ), "foo", "()V" ) );
pthread_create( &thread, NULL, run, NULL );
}
void* run( void* )
{
JNIEnv* jnv;
jvm->AttachCurrentThread( &jnv, NULL );
/*
Within the context of our thread however, this crashes:
*/
jnv->CallVoidMethod( object, jnv->GetMethodID( jnv->GetObjectClass( object ), "foo", "()V" ) );
jvm->DetachCurrentThread( );
return NULL;
}
Any ideas as to what's going wrong?
Okay, the problem seemed to be a missing NewGlobalRef call. This version works:
#include <jni.h>
#include <pthread.h>
pthread_t thread;
jobject object;
JavaVM* jvm;
/*
Our thread function:
*/
void* run( void* );
extern "C" void Java_com_Program_Initialize( JNIEnv* jnv, jobject caller )
{
object = jnv->NewGlobalRef( caller );
jnv->GetJavaVM( &jvm );
pthread_create( &thread, NULL, run, NULL );
}
void* run( void* )
{
JNIEnv* jnv;
jvm->AttachCurrentThread( &jnv, NULL );
jnv->CallVoidMethod( object, jnv->GetMethodID( jnv->GetObjectClass( object ), "foo", "()V" ) );
jnv->DeleteGlobalRef( object );
jvm->DetachCurrentThread( );
return NULL;
}
I'd like to suggest you to try to find a way to post the invocation to main thread.
Since the entire process from "AttachCurrentThread" to "DetachCurrentThread" is not locked, the main thread may re"AttachCurrentThread", in some case, before the "run" finished. Thus there would still be issues.
Related
Assume the code below demonstrating a binary semaphore example.
In this example, we have a pthread that reads the source.txt and attempts to copy the content to destination.txt while locking it using a binary semaphore.
What happens in the comment section below without the semaphore?
#include <cstdlib>
#include <memory>
#include <filesystem>
#define _TIMESPEC_DEFINED
#include <pthread.h>
#include <semaphore.h>
#include <thread>
#include <valarray>
pthread_t StartFileAccessThread();
void *CopyFile(void *parameters);
int main(int argc, char* argv[])
{
pthread_t thread = StartFileAccessThread();
void *returnValue;
pthread_join(thread, &returnValue);
getchar();
return EXIT_SUCCESS;
}
pthread_t StartFileAccessThread()
{
std::string sourcePath("source.txt");
std::string destinationPath("dest.txt");
sem_t semaphore;
sem_init(&semaphore, 0, 0);
pthread_t thread;
void *parameters[3];
parameters[0] = &semaphore;
parameters[1] = &sourcePath;
parameters[2] = &destinationPath;
pthread_create(&thread, nullptr, &CopyFile, parameters);
// What happens without the binary semaphore?
sem_wait(&semaphore);
sem_destroy(&semaphore);
printf("Freeing ressources.\n");
return thread;
}
void *CopyFile(void *rawParameter)
{
void **parameters = static_cast<void **>(rawParameter);
sem_t *semaphore = static_cast<sem_t *>(parameters[0]);
std::string sourcePath(*static_cast<std::string *>(parameters[1]));
std::string destinationPath(*static_cast<std::string *>(parameters[2]));
sem_post(semaphore);
std::this_thread::sleep_for(std::chrono::seconds(2));
copy_file(sourcePath, destinationPath, std::experimental::filesystem::copy_options::overwrite_existing);
printf("File copied \n");
return nullptr;
}
What happens in the comment section below without the semaphore?
Without the semaphore, function startFileAccessThread() may return before the new thread finishes (or starts) copying its parameters from the argument object. That object is local to startFileAccessThread(), so its lifetime ends when that function returns. Undefined behavior results if the copy thread's accesses to it do not happen before that.
I'm writing a DLL in C++Builder XE6, that creates a separate thread (derived from TThread) to retrieve JSON data from a REST server every X seconds (using TIdHTTP), and parse the JSON data.
The thread fills a simple struct (no dynamically allocated data) with the parsed JSON data in the Execute() method of the thread:
typedef struct
{
char MyString[40 + 1];
double MyDouble;
bool MyBool;
} TMyStruct;
The thread should store the struct in a list, for example a std::vector:
#include <vector>
std::vector<TMyStruct> MyList;
The thread will add a TMyStruct to the list:
TMyStruct Data;
...
MyList.push_back(Data);
The list will be guarded by a TCriticalSection to prevent data corruption.
The DLL exports a function to retrieve a TMyStruct from MyList.
bool __declspec(dllexport) __stdcall GetMyStruct (int Index, TMyStruct* Data)
{
...
}
Only thing is, I don't know where to put MyList...
If I make MyList a global variable, it is located in the main thread's memory and GetMyStruct() can access it directly. How does the thread access MyList?
If I make MyList a member of the TThread-derived class, it is located in the thread's memory and the thread can access it directly. How does GetMyStruct() access MyList?
What is the best/prefered/common way to store MyList and access it in a different thread?
If I make MyList a global variable, it is located in the main thread's memory and GetMyStruct() can access it directly. How does the thread access MyList?
The exact same way. All threads in a process can freely access global variables within that process. For example:
#include <vector>
#include <System.SyncObjs.hpp>
typedef struct
{
char MyString[40 + 1];
double MyDouble;
bool MyBool;
} TMyStruct;
std::vector<TMyStruct> MyList;
TCriticalSection *Lock = NULL; // why not std::mutex instead?
class TMyThread : public TThread
{
...
};
TMyThread *Thread = NULL;
...
void __fastcall TMyThread::Execute()
{
TMyStruct Data;
...
Lock->Enter();
try {
MyList.push_back(Data);
}
__finally {
Lock->Leave();
}
...
}
...
void __declspec(dllexport) __stdcall StartThread ()
{
Lock = new TCriticalSection;
Thread = new TMyThread;
}
void __declspec(dllexport) __stdcall StopThread ()
{
if (Thread) {
Thread->Terminate();
Thread->WaitFor();
delete Thread;
Thread = NULL;
}
if (Lock) {
delete Lock;
Lock = NULL;
}
}
bool __declspec(dllexport) __stdcall GetMyStruct (int Index, TMyStruct* Data)
{
if (!(Lock && Thread)) return false;
Lock->Enter();
try {
*Data = MyList[Index];
}
__finally {
Lock->Leave();
}
return true;
}
If I make MyList a member of the TThread-derived class, it is located in the thread's memory and the thread can access it directly. How does GetMyStruct() access MyList?
By accessing it via a pointer to the thread object. For example:
#include <vector>
#include <System.SyncObjs.hpp>
typedef struct
{
char MyString[40 + 1];
double MyDouble;
bool MyBool;
} TMyStruct;
class TMyThread : public TThread
{
protected:
void __fastcall Execute();
public:
__fastcall TMyThread();
__fastcall ~TMyThread();
std::vector<TMyStruct> MyList;
TCriticalSection *Lock;
};
TMyThread *Thread = NULL;
...
__fastcall TMyThread::TMyThread()
: TThread(false)
{
Lock = new TCriticalSection;
}
__fastcall TMyThread::~TMyThread()
{
delete Lock;
}
void __fastcall TMyThread::Execute()
{
TMyStruct Data;
...
Lock->Enter();
try {
MyList.push_back(Data);
}
__finally {
Lock->Leave();
}
...
}
void __declspec(dllexport) __stdcall StartThread ()
{
Thread = new TMyThread;
}
void __declspec(dllexport) __stdcall StopThread ()
{
if (Thread) {
Thread->Terminate();
Thread->WaitFor();
delete Thread;
Thread = NULL;
}
}
bool __declspec(dllexport) __stdcall GetMyStruct (int Index, TMyStruct* Data)
{
if (!Thread) return false;
Thread->Lock->Enter();
try {
*Data = Thread->MyList[Index];
}
__finally {
Thread->Lock->Leave();
}
return true;
}
What is the best/prefered/common way to store MyList and access it in a different thread?
That is entirely up to you to decide, based on your particular needs and project design.
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.
So I am new to system programming and learning threads.What does the term posix means? I need help in understanding the following code.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *print_message_function( void *ptr );
main()
{
pthread_t thread1, thread2;
const char *message1 = "Thread 1";
const char *message2 = "Thread 2";
int iret1, iret2;
iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
printf("Thread 1 returns: %d\n",iret1);
printf("Thread 2 returns: %d\n",iret2);
exit(0);
}
void *print_message_function( void *ptr )
{
char *message;
message = (char *) ptr;
printf("%s \n", message);
}
I dont understand the line: pthread_join( thread1, NULL);
and the function: void *print_message_function( void *ptr ).
Also, what does the variable iret returns?
It spawns two threads.
Saves their "return values" to variables previously declared.
Joins to threads, basically waits for them to stop.
Prints the variables
exits with status 0, normal successful exit
posix is a general standard for Unix like operating systems. E.g file structure etc
You should read posix documentation.
I dont understand the line: pthread_join( thread1, NULL); and the
function: void *print_message_function( void *ptr ).
pthread_join blocks until the thread terminates
void *print_message_function( void *ptr ) is a function returning void* and receiving a void* as parameter
Again, you should read posix documentation (and learn more C).
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