I'm trying to use QueueUserAPC to run some function asyncronously on a specific thread. My code is working ok when compiled for x64, but when I compile and run for x86, I get an access violation.
At the end of my post is a minimal, complete example that shows what I am trying to do (cleanup of thread and events omitted for brevity).
On my machine, when I compile and run for "x64", I get the expected output:
waiting...
async function!
waiting...
async function!
waiting...
ConsoleApplication3.exe (process 17100) exited with code 0.
When I compile and run for "x86", I get:
waiting...
async function!
And then the access violation, here:
if (WaitForSingleObjectEx(param, INFINITE, TRUE) == WAIT_OBJECT_0)
Exception thrown at 0x776227FB (ntdll.dll) in ConsoleApplication3.exe: 0xC0000005: Access violation reading location 0x36623194.
What am I doing wrong?
Full example:
#include "pch.h"
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <conio.h>
DWORD ThreadFunction(LPVOID param)
{
while (true)
{
printf("waiting...\n");
if (WaitForSingleObjectEx(param, INFINITE, TRUE) == WAIT_OBJECT_0)
break;
}
ExitThread(0);
return 0;
}
void AsyncFunction(UINT_PTR param)
{
printf("async function!\n");
}
int main()
{
HANDLE hThread, hStopEvent;
DWORD threadID;
hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunction, hStopEvent, 0, &threadID);
Sleep(1000);
QueueUserAPC((PAPCFUNC) AsyncFunction, hThread, NULL);
Sleep(1000);
QueueUserAPC((PAPCFUNC) AsyncFunction, hThread, NULL);
Sleep(1000);
SetEvent(hStopEvent);
WaitForSingleObject(hThread, INFINITE);
}
There are two mistakes with my AsyncFunction definition:
1 - The parameter type should be ULONG_PTR, not UINT_PTR. This was actually a copy-paste error from my real implementation
2 - Missing calling convention from the function
void AsyncFunction(UINT_PTR param) should be void CALLBACK AsyncFunction(ULONG_PTR param)
And then there is no need for the cast to PAPCFUNC here:
QueueUserAPC((PAPCFUNC) AsyncFunction, hThread, NULL);
Related
here I come again with a new question for this (blasted) threads programming.
Here is my code, hope you can help me understand what's wrong with it (keep in mind I had to write this code again, not copy-paste, so there may be some type errors - the compiled code is ok and works, so the problem is not the syntax).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
int i=0;
void *TFun(void *TArg)
{
printf("THREAD i=%d\n", i);
i++;
return NULL;
}
int main()
{
pthread_t TID;
TID=pthread_create(&TID, NULL, TFun, NULL);
pthread_join(TID, NULL);
printf("THREAD i=%d\n", i);
i++;
exit(0);
}
I expect this to print "THREAD i=0" and then "MAIN i=1", but this doesn't happen. it only prints "MAIN i=0", the Thread is not executed.
https://i.ibb.co/Y0KYWCK/code.png
https://i.ibb.co/pznZ3TT/result.png
The value of TID is normally written by reference within pthread_create(), but was also being overwritten with the int return value; change to an added int variable:
(old)
TID=pthread_create(&TID, NULL, TFun, NULL);
(new)
int pcr;
pcr = pthread_create(&TID, NULL, TFun, NULL);
I'm using pthread_create to use a function from shared library. I receive Segmenation fault after the following code executes:
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include<string.h>
#include<pthread.h>
#include<unistd.h>
void (*GetVersion)(char *version);
void* draw(void *arg)
{
void *handle;
char *error;
handle = dlopen ("libOpenKaillera.so", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
GetVersion = dlsym(handle, "GetVersion");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
char version[4];
kailleraGetVersion(version);
puts(version);
dlclose(handle);
return NULL;
}
int main(void)
{
pthread_t tid;
pthread_create(&tid, NULL, &draw, NULL);
sleep(5000);
return 0;
}
The backtrace command says the following:
#0 0xb68e7be0 in ?? ()
#1 0xb7fa9d56 in __nptl_deallocate_tsd () at pthread_create.c:158
#2 0xb7fa9f83 in start_thread (arg=0xb7df0b40) at pthread_create.c:325
#3 0xb7ede4ce in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:129
I don't understand what a reason can cause this. Can you help me please?
after each calling of pthread_create, please remember to call pthread_join or pthread_detach to tell the thread how to perform termination. normally, please call pthread_join before exiting the creating thread (in this case, it is function main).
Google breakpad catches signal (about crash in native code via JNI) but the app still dies after it. What should be done in order to prevent it?
log:
03-08 15:04:13.398: ERROR/NATIVE_LIB(2828): init breakpad
03-08 15:04:13.398: ERROR/NATIVE_LIB(2828): testing crash
03-08 15:04:13.468: ERROR/NATIVE_LIB(2828): Dump path: ./5f6097b2-5feb-0723-3271a7ff-2a4fcadd.dmp
03-08 15:04:13.468: WARN/crash_handler(2828): Caught a crash, signum=11
...
03-08 15:04:14.589: INFO/ActivityManager(544): Process name.antonsmirnov.android.app (pid 2828) has died.
code:
#include "native_lib.h"
#include <stdio.h>
#include "client/linux/handler/exception_handler.h"
#include "client/linux/handler/minidump_descriptor.h"
#include <android/log.h>
void debug(const char *format, ... ) {
va_list argptr;
va_start(argptr, format);
__android_log_vprint(ANDROID_LOG_ERROR, "NATIVE_LIB", format, argptr);
va_end(argptr);
}
bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
void* context,
bool succeeded) {
debug("Dump path: %s\n", descriptor.path());
return succeeded;
}
JNIEXPORT jint JNICALL Java_name_antonsmirnov_android_app_libnative_func(JNIEnv *env, jobject obj)
{
debug("init breakpad");
google_breakpad::MinidumpDescriptor descriptor(".");
google_breakpad::ExceptionHandler eh(descriptor, NULL, DumpCallback, NULL, true, -1);
{
debug("testing crash\n");
char *ptr = 0;
*ptr = '!'; // ERROR HERE!
debug("unreachable\n");
}
debug("finished\n");
}
In some cases, there is no way of preventing your app from crashing, even if you use Breakpad or CoffeeCatch.
However, you will be notified before the crash occurs. You can use that time to warn the user about what is happening (a fatal error) and what will happen next (the app will force close).
This Code is pretty fine to demonstrate Critical Section problem, but i've TWO QUERIES about the code,
How to show WHICH THREAD is being rejected to Enter in Critical Section ?
thread 'A', 'B', 'C' are created in listed order. HOW can i start them at single time ?
Here is the code:
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
void *doSomething1();
void *doSomething2();
void *doSomething3();
sem_t sem;
int main() {
// initialize semaphore to 2
sem_init(&sem, 1, 2);
pthread_t thread1, thread2, thread3;
pthread_create(&thread1, NULL, &doSomething1, NULL);
pthread_create(&thread2, NULL, &doSomething2, NULL);
pthread_create(&thread3, NULL, &doSomething3, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_join(thread3, NULL);
return 0;
}
void doSomething(char c) {
int i, time;
for (i = 0; i < 3; i++) {
if (sem_wait(&sem) == 0) {
// generate random amount of time (< 7 seconds)
time = (int) ((double) rand() / RAND_MAX * 7 );
printf("#thread %c GOT-ACCESS to CRITICAL SESSION for %d sec\n", c, time);
sleep(time);
printf("\t->thread %c RELEASED CRITICAL SESSION\n",c);
sem_post(&sem);
}
else
printf("thread %c FAILED TO ENTER CRITICAL SECTION",c);
}
}
void *doSomething1() {
// thread A
doSomething('A'); return 0;
}
void *doSomething2() {
// thread B
doSomething('B'); return 0;
}
void *doSomething3() {
// thread C
doSomething('C'); return 0;
}
In order for a thread to be "rejected" from entering you would have to replace sem_wait(), which is a blocking call with sem_trywait()or sem_timedwait()although then they might not ever enter the critical section (without some more modifications to the code). But since you only want to see when a thread is denied entering the section this should be sufficient. (for more information on these methods visit the man page http://linux.die.net/man/3/sem_wait ).
As for the second the question the answer is that you actually cannot start all threads at once, they have to start in some sort of order. However you can (if you want) start multiple threads and use a semaphore to block them until all threads are ready and then release them all at once, which is as close as you can get to starting them at once.
I have a thread which blocks until data is received from a system resources such as a USB device. I chose this model because the amount of data may vary, and data may be received at any time. Upon exiting the application, I get the message “QThread: Destroyed while thread is still running”. How should I go about closing these threads?
I’ve looked at other problems/solutions such as:
http://www.qtcentre.org/threads/14429-Loop-inside-Qthread-causes-quot-QThread-Destroyed-while-thread-is-still-running-quot
http://www.qtcentre.org/threads/6211-QThread-Destroyed-while-thread-is-still-running
The first solution involves using a flag (included in my code) however my thread will never reach the flag check.
The second solution uses QWaitCondition but seem to be along the same lines as the first.
I’ve included a stripped down version of the code below. The system calls WaitForSingleObject() is a substitute for what I actually use (GetOverlappedResult()).
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <QObject>
#include <QThread>
#include <QReadWriteLock>
#include <QDebug>
#ifdef Q_OS_WIN
#include <windows.h>
#endif // Q_OS_WIN
#ifdef Q_OS_LINUX
#include <unistd.h>
#endif // Q_OS_LINUX
////////////////////////////////////////////////
//
// Worker Object
//
////////////////////////////////////////////////
class Worker : public QObject {
Q_OBJECT
public:
QReadWriteLock lock;
bool running;
public slots:
void loop() {
qDebug() << "entering the loop";
bool _running;
forever {
lock.lockForRead();
_running = running;
lock.unlock();
if (!_running) return;
qDebug() << "loop iteration";
#ifdef Q_OS_WIN
HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
WaitForSingleObject(event, INFINITE);
#endif // Q_OS_WIN
#ifdef Q_OS_LINUX
read(0, 0, 1);
#endif // Q_OS_LINUX
}
}
};
////////////////////////////////////////////////
//
// Controller
//
////////////////////////////////////////////////
class Controller {
public:
Controller() {
myWorker.connect(&myThread, SIGNAL(started()), &myWorker, SLOT(loop()));
myWorker.moveToThread(&myThread);
myThread.start();
}
~Controller() {
// Safely close threads
myWorker.lock.lockForWrite();
myWorker.running = false;
myWorker.lock.unlock();
myThread.quit();
//myThread.wait();
//myThread.exit();
//myThread.terminate();
}
private:
QThread myThread;
Worker myWorker;
};
#endif // CONTROLLER_H
For Linux:
Sending a signal to the thread with pthread_kill() interrupted read() with failure code EINTR. sigaction() was used to register the signal, and the signal thrown was SIGUSR1.
// Global scope
void nothing(int signum) {}
...
// Within the start of the thread
pthread_t myThreadID = pthread_self(); // Get the thread ID
struct sigaction action;
action.sa_flags = 0;
sigemptyset(&action.sa_mask);
action.sa_handler = nothing;
sigaction(SIGUSR1, &action, NULL);
...
// When it's time to close the thread
pthread_kill(myThreadID, SIGUSR1);
For Windows:
Signaling the OVERLAPPED's hEvent with SetEvent() was used to unblock GetOverlappedResult().
// Store a reference to the event
HANDLE myEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
...
// Within the start of the thread
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = myEvent;
...
// When it's time to close the thread
SetEvent(myEvent);