User triggered event in libevent - 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()).

Related

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.

What are my errors using libevent timout events?

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

C Callback in Objective-C (IOKIT)

I am trying to write some code that interacts with an USB device in Objective C, and I got stuck on setting the callback function for incoming reports. In my case it's an IOKIT function but I think the problem is more general as I (apparently) don't know how to correctly set a C callback function in Objective-C. I've got a Class "USBController" that handles the io functions
USBController.m:
#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h>
#include <IOKit/hid/IOHIDLib.h>
#import "USBController.h"
static void Handle_IOHIDDeviceIOHIDReportCallback(
void * inContext, // context from IOHIDDeviceRegisterInputReportCallback
IOReturn inResult, // completion result for the input report operation
void * inSender, // IOHIDDeviceRef of the device this report is from
IOHIDReportType inType, // the report type
uint32_t inReportID, // the report ID
uint8_t * inReport, // pointer to the report data
CFIndex InReportLength) // the actual size of the input report
{
printf("hello"); //just to see if the function is called
}
#implementation USBController
- (void)ConnectToDevice {
...
IOHIDDeviceRegisterInputReportCallback(tIOHIDDeviceRefs[0], report, reportSize,
Handle_IOHIDDeviceIOHIDReportCallback,(void*)self);
...
}
...
#end
All the functions are also declared in the header file.
I think I did pretty much the same as what I've found here, but it doesn't work. The project compiles nicely and everything works up till the moment there is input and the callback function is to be called. Then I get an "EXC_BAD_ACCESS" error. The first three arguments of the function are correct. I'm not so sure about the context..
What did I do wrong?
I am not sure at all that your EXEC_BAD_ACCESS depends on your callback. Indeed, if you say that it is called (I suppose you see the log) and since it only logs a message, there should be no problem with this.
EXEC_BAD_ACCESS is caused by an attempt to access an already deallocated object. You can get more information in two ways:
execute the program in debug mode, so when it crashes you will be able to see the stack content;
activate NSZombies or run the program using the performance tool Zombies; this will tell you exactly which object was accessed after its deallocation.
I know how to fix this. When calling this:
IOHIDDeviceRegisterInputReportCallback(tIOHIDDeviceRefs[0], report, reportSize,
Handle_IOHIDDeviceIOHIDReportCallback,(void*)self);
You don't include the code for the creation/type of the value called report. However the method name "Handle_IOHIDDeviceIOHIDReportCallback" comes from an Apple document where there is an error in the creation of the report value. https://developer.apple.com/library/archive/technotes/tn2187/_index.html
CFIndex reportSize = 64;
uint8_t report = malloc( reportSize ); // <---- WRONG
IOHIDDeviceRegisterInputReportCallback( deviceRef,
report,
reportSize,
Handle_IOHIDDeviceIOHIDReportCallback,
context );
Instead do this:
uint8_t *report = (uint8_t *)malloc(reportSize);

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

Best way to know if application is inactive in cocoa mac OSX?

So, i am building a program that will stand on a exhibition for public usage, and i got a task to make a inactive state for it. Just display some random videos from a folder on the screen, like a screensaver but in the application.
So what is the best and proper way of checking if the user is inactive?
What i am thinking about is some kind of global timer that gets reset on every user input and if it reaches lets say 1 minute it goes into inactive mode. Are there any better ways?
You can use CGEventSourceSecondsSinceLastEventType
Returns the elapsed time since the last event for a Quartz event
source.
/*
To get the elapsed time since the previous input event—keyboard, mouse, or tablet—specify kCGAnyInputEventType.
*/
- (CFTimeInterval)systemIdleTime
{
CFTimeInterval timeSinceLastEvent = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType);
return timeSinceLastEvent;
}
I'm expanding on Parag Bafna's answer. In Qt you can do
#include <ApplicationServices/ApplicationServices.h>
double MyClass::getIdleTime() {
CFTimeInterval timeSinceLastEvent = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType);
return timeSinceLastEvent;
}
You also have to add the framework to your .pro file:
QMAKE_LFLAGS += -F/System/Library/Frameworks/ApplicationServices.framework
LIBS += -framework ApplicationServices
The documentation of the function is here
I've found a solution that uses the HID manager, this seems to be the way to do it in Cocoa. (There's another solution for Carbon, but it doesn't work for 64bit OS X.)
Citing Daniel Reese on the Dan and Cheryl's Place blog:
#include <IOKit/IOKitLib.h>
/*
Returns the number of seconds the machine has been idle or -1 on error.
The code is compatible with Tiger/10.4 and later (but not iOS).
*/
int64_t SystemIdleTime(void) {
int64_t idlesecs = -1;
io_iterator_t iter = 0;
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
IOServiceMatching("IOHIDSystem"),
&iter) == KERN_SUCCESS)
{
io_registry_entry_t entry = IOIteratorNext(iter);
if (entry) {
CFMutableDictionaryRef dict = NULL;
kern_return_t status;
status = IORegistryEntryCreateCFProperties(entry,
&dict,
kCFAllocatorDefault, 0);
if (status == KERN_SUCCESS)
{
CFNumberRef obj = CFDictionaryGetValue(dict,
CFSTR("HIDIdleTime"));
if (obj) {
int64_t nanoseconds = 0;
if (CFNumberGetValue(obj,
kCFNumberSInt64Type,
&nanoseconds))
{
// Convert from nanoseconds to seconds.
idlesecs = (nanoseconds >> 30);
}
}
CFRelease(dict);
}
IOObjectRelease(entry);
}
IOObjectRelease(iter);
}
return idlesecs;
}
The code has been slightly modified, to make it fit into the 80-character limit of stackoverflow.
This might sound like a silly question; but why not just set up a screensaver, with a short fuse?
You can listen for the NSNotification named #"com.apple.screensaver.didstart" if you need to do any resets or cleanups when the user wanders away.
Edit: You could also set up the screen saver; wait for it to fire, and then do your own thing when it starts, stopping the screen saver when you display your own videos; but setting up a screen saver the proper way is probably a good idea.
Take a look at UKIdleTimer, maybe it's what you're looking for.