What are my errors using libevent timout events? - libevent

I am trying to learn libevent for use in a future project. I am attempting to create a event that calls it's call back function each time it times out. All the call back function does is print "timeout_cb called" to standard out.
my code for the call back function is:
static void timeout_cb(evutil_socket_t fd, short what, void *arg) {
printf("timeout_cb called");
}
my code for the event is:
struct event *toEvent; // time out event do this every so often
toEvent = event_new(base, -1, EV_TIMEOUT, timeout_cb, NULL); // base is the event base
event_add(toEvent, &five_seconds); //five_seconds is a timeval struct with 5 seconds
The program will compile and run with no errors or warnings but it doesn't print out the phrase in the call back function. I have used similar printf statements in other callback types to verify they were called and that various lines were reached inside the functions, but this does nothing. I waited 30 seconds or so but still nothing printed to the screen. What am I doing wrong the with the pure timeout event.

You'll have to do
event_new(base, -1, 0, timeout_cb, NULL);
Note that there's some convenience macros to add timers, evtimer_new(), evtimer_add(), see the docs

Related

QThread always stuck in wait

I am trying to use QThread to call a function in another thread without having the UI to freeze. I am using QT5.11.2 on both windows and linux.
Everything works fine on windows but the wait() function for QThread never returns no matter what.
I use RHEL7 on linux
Here is what I am doing:
void MainWidget::configure_click(double value)
{
QThread *myThread = QThread::create([this, value]{ Configure(value); });
dsoThread->setObjectName("My Configure Thread");
QObject::connect(myThread, &QThread::finished, [](){ qDebug()<< "Configure Thread has finished";}); // This is never printed
myThread->start();
myThread->wait(); // Never returns from this
myThread->quit();
myThread->deleteLater();
}
My Configure function prints its start and finish and both lines are being printed on run time
void MainWidget::Configure(double value)
{
qDebug() << QThread::currentThread() << " started";
// Code to execute
qDebug() << QThread::currentThread() << " finished";
}
I even read that quit() forces the thread to stop, so just for testing I tried switching quit() and wait() like so
myThread->quit();
myThread->wait(); // Never returns from this either
myThread->deleteLater();
I even tried looping the isRunning() function instead of wait() but I got the same results
while(myThread->isRunning()) // Same goes for !isFinished()
{
// Do nothing
}
It seems like no matter what the thread never knows that it was finished.
What can I do to either solve this problem or to check why this is happening?
You haven't start()ed the thread.
myThread->wait(); in gui thread waits for thread to terminate so it blocks gui thread event loop, so you lose all benifints of threading this way and might as well just do Configure(value); without threading.
Documentation says:
wait() and the sleep() functions should be unnecessary in
general, since Qt is an event-driven framework. Instead of
wait(), consider listening for the finished() signal. Instead of
the sleep() functions, consider using QTimer.

Check the condition when a timer is running in CAPL (CANoe)

I am running a script in CAPL where I am supposed to notice a change in the value of a signal (for example: signal B) coming from the ECU. At the start of the timer, I change the value of another signal (for example: signal A) and sent it to ECU over CAN Bus. While the timer is running, I want to see the changed value of signal B coming from ECU as a response to the changed value of signal A. After the timer has run out, I want to reset the signal A back to its original value.
*Note: I have called the different signals as Signal A and Signal B only for understanding the question more clearly
Signal A changes the value from 2 to 0.
Signal B has original value of 61, and the changed value can be any number between 0-60.
Timer runs for 4 seconds.
I am using while loop and command (isTimerActive(timer)==1), to check for the change in the value of signal B when the timer is running.
Below is the attached Code ->
variables
{
msTimer Execute;
}
on key 'c'
{
setTimer(Execute,4000);
Write("Test starts");
SetSignal(Signal A, 2);
while (isTimerActive(Execute)==1)
{
if ($Signal B != 61)
{
Write("Test pass");
}
else
{
Write("Test fail");
}
}
}
on timer Execute
{
write("Test over");
setSignal(Signal A, 0);
}
I am executing this code and the value of signal A changes to 2 but
there's no change in the value of signal B. I am using the
(isTimerActive (timer) ==1) in the while loop, is it the correct command
for my problem?
Also, when I run (isTimerActive (timer) ==1), CANoe becomes inactive and
I have to stop CANoe using Task manager.
Any ideas how can I correct my code and get the desired response?
Thanks and Best
CAPL is event-driven. Your only choice is to react on events by programming event handlers, i.e. the functions starting with on ....
During execution of an event handler, the system basically blocks everything until the event handler has finished.
Literally nothing else happens, no sysvars change, no signals change, no timers expire, no bus messages are handled, and so on.
For test-modules and -units the story is a little bit different. There you have the possibility to wait during execution of your code using the various testWaitFor... methods.
With your current implementation of on key ‘c‘you basically block the system, since you have an while loop there waiting for an Timer to expire.
As stated above, this blocks everything and you have to kill CANoe.
Fortunately changes of signals are also events that can be handled.
Something like this should do:
Remove the while block and instead add another event handler like this:
on signal SignalB
{
if(isTimerActive(Execute))
{
if ($SignalB != 61)
{
Write("Test pass");
}
else
{
Write("Test fail");
}
}
}
The code is called when SignalB changes. It then checks whether the Timer is still running and checks the value of the signal.
Instead of $SignalB inside of the handler you can also write this.
In an event handler this is always the object that has caused the event.

How to force a libusb event so that libusb_handle_events() returns

Suppose I have a libusb program that just uses the hotplug API. You register a callback and then apparently have to call libusb_handle_events() in a loop which then calls your hotplug callback.
int LIBUSB_CALL hotplugCallback(libusb_context* ctx,
libusb_device* device,
libusb_hotplug_event event,
void* user_data)
{
cout << "Device plugged in or unplugged";
}
void main()
{
libusb_init(nullptr);
libusb_hotplug_register_callback(nullptr,
static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
LIBUSB_HOTPLUG_NO_FLAGS,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
&hotplugCallback,
this,
&hotplugCallbackHandle);
for (;;)
{
if (libusb_handle_events_completed(nullptr, nullptr) != LIBUSB_SUCCESS)
return 1;
}
return 0;
}
The question is, without timeout hacks how can I exit this event loop cleanly? I can't find any functions that force libusb_handle_events() (or libusb_handle_events_completed()) to return. In theory they could just never return.
Sorry if this is late.
The question could have been phrased better but I'm assuming (from your comment updates) that your actual program resembles something a little closer to this:
int LIBUSB_CALL hotplugCallback(libusb_context *ctx,
libusb_device *device,
libusb_hotplug_event event,
void *user_data) {
cout << "Device plugged in or unplugged";
}
void SomeClass::someFunction() {
libusb_init(nullptr);
libusb_hotplug_register_callback(nullptr,
static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
LIBUSB_HOTPLUG_NO_FLAGS,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
&hotplugCallback,
this,
&hotplugCallbackHandle);
this->thread = std::thread([this]() {
while (this->handlingEvents) {
int error = libusb_handle_events_completed(context, nullptr);
}
});
}
Let's say your object is being deallocated and, no matter what is happening on the USB bus, you don't care and you want to clean up your thread.
You negate this->handlingEvents and you call thread.join() and the thread hangs for 60 seconds and then execution resumes.
This is done because the default behavior of libusb_handle_events_completed calls libusb_handle_events_timeout_completed and passes in a 60 second timeout interval with plans to make it infinite.
The way you force libusb_handle_events_completed to return is you call libusb_hotplug_deregister_callback which wakes up libusb_handle_events(), causing the function to return.
There is more info about this behavior in the docs.
So your destructor (or wherever you want to stop listening immediately) for the class could look something like this:
SomeClass::~SomeClass() {
this->handlingEvents = false;
libusb_hotplug_deregister_callback(context, hotplugCallbackHandle);
if (this->thread.joinable()) this->thread.join();
libusb_exit(this->context);
}
In the function:
int libusb_handle_events_completed(libusb_context* ctx, int* completed)
You can change the value of the completed to "1" so the function will return without blocking
According to their docs:
If the parameter completed is not NULL then after obtaining the event
handling lock this function will return immediately if the integer
pointed to is not 0. This allows for race free waiting for the
completion of a specific transfer.
There is no functions in libusb that force libusb_handle_events() to return.
It's recommended to use libusb_handle_events() in a dedicated thread so your main thread will not be blocked by this call. Even though, if you need to manipulate the call of the event handler you can put the call in a while(condition) and change the condition state in your main thread.
Libusb documentation details this here.

User triggered event in libevent

I am currently writing a multi-threaded application using libevent.
Some events are triggered by IO, but I need a couple of events that are triggered accross threads by the code itself, using event_active().
I have tried to write a simple program that shows where my problem is:
The event is created using event_new(), and the fd set to -1.
When calling event_add(), if a timeout struct is used, the event is later properly handled by event_base_dispatch.
If event_add(ev, NULL) is used instead, it returns 0 (apparently successful), but event_base_dispatch() returns 1 (which means no the event was not properly registered.)
This behavior can be tested using the following code and swapping the event_add lines:
#include <event2/event.h>
#include <unistd.h>
void cb_func (evutil_socket_t fd, short flags, void * _param) {
puts("Callback function called!");
}
void run_base_with_ticks(struct event_base *base)
{
struct timeval one_sec;
one_sec.tv_sec = 1;
one_sec.tv_usec = 0;
struct event * ev1;
ev1 = event_new(base, -1, EV_PERSIST, cb_func, NULL);
//int result = event_add(ev1, NULL);
int result = event_add(ev1, &one_sec);
printf("event_add result: %d\n",result);
while (1) {
result = event_base_dispatch(base);
if (result == 1) {
printf("Failed: event considered as not pending dispite successful event_add\n");
sleep(1);
} else {
puts("Tick");
}
}
}
int main () {
struct event_base *base = event_base_new();
run_base_with_ticks(base);
return 0;
}
Compilation: g++ sample.cc -levent
The thing is, I do not need the timeout, and do not want to use a n-years timeout as a workaround. So if this is not the right way to use user-triggered events, I would like to know how it is done.
Your approach is sound. In Libevent 2.0, you can use event_active() to activate an event from another thread. Just make sure that you use evthread_use_windows_threads() or evthread_use_pthreads() as appropriate beforehand, to tell Libevent to use the right threading library.
As for needing an extra event: in Libevent 2.0 and earlier, an event loop will exit immediately when there are no pending events added. Your best bet there is probably the timeout trick you discovered.
If you don't like that, you can use the internal "event_base_add_virtual" function to tell the event_base that it has a virtual event. This function isn't exported, though, so you'll have to say something like:
void event_base_add_virtual(struct event_base *);
// ...
base = event_base_new();
event_base_add_virtual(base); // keep it from exiting
That's a bit of a hack, though, and it uses an undocumented function, so you'd need to watch out in case it doesn't work with a later version of Libevent.
Finally, this method won't help you now, but there's a patch pending for future versions of Libevent (2.1 and later) to add a new flag to event_base_loop() to keep it from exiting when the loop is out of events. The patch is over on Github; it is mainly waiting for code review, and for a better name for the option.
I just got burned by this with libevent-2.0.21-stable. It is quite clearly a bug. I hope they fix it in a future release. In the meantime, updating the docs to warn us about it would be helpful.
The best workaround seems to be the fake timeout as described in the question.
#nickm, you didn't read the question. His example code uses event_new() like you described; there is a bug in libevent that causes it to fail when using a NULL timeout (but return 0 when you call event_add()).

How to catch application titlebar change?

We are running on a Windows Client Platform (generally WinXP) in niche industry program that runs in a 640x480 window back to an AS/400 server. To reduce errors I want to watch for when the title bar of the program changes. Then I need to capture the keyboard entries to validate. I'll then make sure each of the entries is valid since the archaic program does no validation. I'll can then do a pop-up then warning the end-user if errors occur and to reduce/eliminate the exception reports.
My question is how can I capture the event of the application title bar change = 'string' that I need? API call? Aiming to do this in VB unless another would be notable cleaner.
WinEvents should work well here. These are lightweight events that get fired when certain UI changes take place - eg names of objects change - which includes Titlebar text changes. One benefit to this type of hook is that you can set it up to deliver the notifications back to your own process, so you don't need to deal with hooking or IPC. (It also works against both 32-bit and 64-bit processes.)
This is easiest to do in plain C/C++; but can be done in .Net (VB, C#) if you add the appropriate [DllImport]'s.
#include <windows.h>
#include <stdio.h>
#define WM_NAMECHANGED WM_APP
HWND g_hwndTarget; // window we're listening to
void CALLBACK WinEventProc(
HWINEVENTHOOK hWinEventHook,
DWORD event,
HWND hwnd,
LONG idObject,
LONG idChild,
DWORD dwEventThread,
DWORD dwmsEventTime
)
{
// Check this is the window we want. Titlebar name changes result in these
// two values (obtained by looking at some titlebar changes with the
// Accessible Event Watcher tool in the Windows SDK)
if(hwnd == g_hwndTarget && idObject == OBJID_WINDOW && idChild == CHILDID_SELF)
{
// Do minimal work here, just hand off event to mainline.
// If you do anything here that has a message loop - eg display a dialog or
// messagebox, you can get reentrancy.
PostThreadMessage(GetCurrentThreadId(), WM_NAMECHANGED, 0, 0);
}
return;
}
void ReportName(HWND hwnd)
{
WCHAR szName[128];
GetWindowText(hwnd, szName, ARRAYSIZE(szName));
wprintf(L"hwnd 0x%08lx has title: %s\n", HandleToLong(hwnd), szName);
}
int main()
{
wprintf(L"Place mouse pointer over window titlebar to report name changes for and hit return...\n");
getchar();
POINT pt;
GetCursorPos(&pt);
g_hwndTarget = WindowFromPoint(pt);
ReportName(g_hwndTarget);
// Note: this doesn't work for console windows, which are managed by CSRSS.EXE. Simplest (though not efficient) workaround for those
// is to use threadId=0 and filter by hwnd in the callback.
DWORD threadId = GetWindowThreadProcessId(g_hwndTarget, NULL);
// This says: call the callback when any UI elements in the specified thread change
// name. _OUTOFCONTEXT means deliver the notifications in this process, don't hook.
HWINEVENTHOOK hook = SetWinEventHook(EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_NAMECHANGE, NULL, WinEventProc, 0, threadId, WINEVENT_OUTOFCONTEXT);
// TODO: add error checking as appropriate.
wprintf(L"Waiting...\n");
// Thread needs to have a message loop for SetWinEventHook to work for out-of-context messages.
UINT count = 10;
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
if(msg.message == WM_NAMECHANGED)
{
ReportName(g_hwndTarget);
if(--count == 0)
{
break;
}
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWinEvent(hook);
return 0;
}
Things to watch for: you might get false-positives; and if the name changes rapidly, by the time you get the first event, the name may be at the second value, so you may appear to see two events for the second value. Neither of these should be an issue if you're just using this as a trigger to check for a specified value, however.
I am assuming that you do not own the code for the target application. In this case, there's no easy "call me back when the title changes" event. You then have 2 options to do what you need, which I will outline below.
Easy but not airtight
Have your application get the main window of the target application (this should be easy enough) and poll its title every 100msec or so. When you detect a change, act accordingly.
Difficult but correct
Hook into the target application using e.g. a global CBT hook. Once your code runs in their process subclass their main window, causing all window messages to go through your code first. When your code sees a WM_SETTEXT message going to the main window, you can actively notify your "other" application on the spot using your choice of IPC. If all you need to do is just shout "hey!" to your other application, do so with an auto-reset event (it will be easiest). Of course all this points heavily to unmanaged code.
If the easy solution is not good enough and the difficult one is too much, you can try using an automation library like White (I 've never used it, so I can't really say more than that).