In an IOCP Winsock2 client, after ConnectEx() times-out on an unsuccessful connection attempt, the following happens:
An "IO completion" is queued to the associated IO Completion Port.
GetQueuedCompletionStatus() returns FALSE.
WSAGetOverlappedResult() returns WSAETIMEDOUT.
What determines the timeout period between calling ConnectEx() and 1 above? How can I shorten this timeout period?
I know that it is possible to wait for ConnectEx() by passing it a filled-out structure OVERLAPPED.hEvent = WSACreateEvent() and then waiting for this event, e.g. with WaitForSingleObject(Overlapped.hEvent, millisec) to timeout after no connection has been made for the millisec time period. BUT, that solution is outside the scope of this question because it does not refer to the IOCP notification model.
unfortunatelly look like no built-in option for set socket connect timeout. how minimum i not view this and based on this question - How to configure socket connect timeout - nobody not view too.
one possible solution pass event handle to I/O request and if we got ERROR_IO_PENDING - call RegisterWaitForSingleObject for this event. if this call will be successful - our WaitOrTimerCallback callback function will be called - or because I/O will be complete (with any final status) and at this moment event (which we pass both to I/O request and RegisterWaitForSingleObject) will be set or because timeout (dwMilliseconds) expired - in this case we need call CancelIoEx function.
so let say we have class IO_IRP : public OVERLAPPED which have reference counting (we need save pointer to OVERLAPPED used in I/O request for pass it to CancelIoEx. and need be sure that this OVERLAPPED still not used in another new I/O - so yet not free). in this case possible implementation:
class WaitTimeout
{
IO_IRP* _Irp;
HANDLE _hEvent, _WaitHandle, _hObject;
static VOID CALLBACK WaitOrTimerCallback(
__in WaitTimeout* lpParameter,
__in BOOLEAN TimerOrWaitFired
)
{
UnregisterWaitEx(lpParameter->_WaitHandle, NULL);
if (TimerOrWaitFired)
{
// the lpOverlapped unique here (because we hold reference on it) - not used in any another I/O
CancelIoEx(lpParameter->_hObject, lpParameter->_Irp);
}
delete lpParameter;
}
~WaitTimeout()
{
if (_hEvent) CloseHandle(_hEvent);
_Irp->Release();
}
WaitTimeout(IO_IRP* Irp, HANDLE hObject) : _hEvent(0), _Irp(Irp), _hObject(hObject)
{
Irp->AddRef();
}
BOOL Create(PHANDLE phEvent)
{
if (HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL))
{
*phEvent = hEvent;
_hEvent = hEvent;
return TRUE;
}
return FALSE;
}
public:
static WaitTimeout* Create(PHANDLE phEvent, IO_IRP* Irp, HANDLE hObject)
{
if (WaitTimeout* p = new WaitTimeout(Irp, hObject))
{
if (p->Create(phEvent))
{
return p;
}
delete p;
}
return NULL;
}
void Destroy()
{
delete this;
}
// can not access object after this call
void SetTimeout(ULONG dwMilliseconds)
{
if (RegisterWaitForSingleObject(&_WaitHandle, _hEvent,
(WAITORTIMERCALLBACK)WaitOrTimerCallback, this,
dwMilliseconds, WT_EXECUTEONLYONCE|WT_EXECUTEINWAITTHREAD))
{
// WaitOrTimerCallback will be called
// delete self here
return ;
}
// fail register wait
// just cancel i/o and delete self
CancelIoEx(_hObject, _Irp);
delete this;
}
};
and use something like
if (IO_IRP* Irp = new IO_IRP(...))
{
WaitTimeout* p = 0;
if (dwMilliseconds)
{
if (!(p = WaitTimeout::Create(&Irp->hEvent, Irp, (HANDLE)socket)))
{
err = ERROR_NO_SYSTEM_RESOURCES;
}
}
if (err == NOERROR)
{
DWORD dwBytes;
err = ConnectEx(socket, RemoteAddress, RemoteAddressLength,
lpSendBuffer, dwSendDataLength, &dwBytes, Irp)) ?
NOERROR : WSAGetLastError();
}
if (p)
{
if (err == ERROR_IO_PENDING)
{
p->SetTimeout(dwMilliseconds);
}
else
{
p->Destroy();
}
}
Irp->CheckErrorCode(err);
}
another possible solution set timer via CreateTimerQueueTimer and if timer expired - call CancellIoEx or close I/O handle from here. difference with event solution - if I/O will be completed before timer expired - the WaitOrTimerCallback callback function will be not automatically called. in case event - I/O subsystem set event when I/O complete (after intial pending status) and thanks to that (event in signal state) callback will be called. but in case timer - no way pass it to io request as parameter (I/O accept only event handle). as result we need save pointer to timer object by self and manually free it when I/O complete. so here will be 2 pointer to timer object - one from pool (saved by CreateTimerQueueTimer) and one from our object (socket) class (we need it for dereference object when I/O complete). this require reference counting on object which incapsulate timer too. from another side we can use timer not for single I/O operation but for several I/O (because it not direct bind to some I/O)
Related
I have an STA COM object that implements a custom interface. My custom interface has a custom proxy stub that was built from the code generated by the MIDL-compiler. I would like to be able to asynchronously make calls to the interface from other apartments. I'm finding that the synchronous interface calls respect the OLE message filter on the calling thread, but the asynchronous interface calls do not. This means that COM asynchronous calls cannot be used in a fire-and-forget manner if the calling apartment has a message filter that suggests retrying the call later.
Is this expected? Is there any way around this other than not using a message filter, not using fire-and-forget operations, or having a separate homegrown component just to manage fire-and-forget operations?
For the code below, MessageFilter is a simple, in-module implementation of IMessageFilter that routes calls to lambdas. If I do not use message filters, both the synchronous and asynchronous calls work fine. If I use the message filters shown below, the synchronous call works (after the main STA message filter stops returning SERVERCALL_RETRYLATER) but the asynchronous call immediately fails and never retries.
The main STA has a message filter that defers for some period of time.
// establish deferral time
chrono::time_point<chrono::system_clock> defer_until = ...;
// create message filter
auto message_filter = new MessageFilter;
message_filter->AddRef();
message_filter->handle_incoming_call
= [defer_until](DWORD, HTASK, DWORD, LPINTERFACEINFO)
{
return chrono::high_resolution_clock::now() >= defer_until
? SERVERCALL_ISHANDLED
: SERVERCALL_RETRYLATER;
};
// register message filter
CoRegisterMessageFilter(message_filter, nullptr);
Another STA sets up its own message filter to tell COM to retry.
// create message filter
auto message_filter = new MessageFilter;
message_filter->AddRef();
message_filter->retry_rejected_call
= [](HTASK, DWORD, DWORD)
{
return 0; // retry immediately
};
// register message filter
CoRegisterMessageFilter(message_filter, nullptr);
In that secondary STA, I get a proxy for the object interface from the main STA.
// get global interface table
IGlobalInterfaceTablePtr global_interface_table;
global_interface_table.CreateInstance(CLSID_StdGlobalInterfaceTable);
// get interface reference
IMyInterfacePtr object_interface;
global_interface_table->GetInterfaceFromGlobal(cookie, __uuidof(IMyInterface), reinterpret_cast<LPVOID*>(&object_interface)));
This works:
// execute synchronously
HRESULT hr = object_interface->SomeMethod();
/* final result, after the deferral period: hr == S_OK */
This does not work:
// get call factory
ICallFactoryPtr call_factory;
object_interface->QueryInterface(&call_factory);
// create async call
AsyncIMyInterfacePtr async_call;
call_factory->CreateCall(__uuidof(AsyncIMyInterface), nullptr, __uuidof(AsyncIMyInterface), reinterpret_cast<LPUNKNOWN*>(&async_call)));
// begin executing asynchronously
async_call->Begin_SomeMethod();
// end executing asynchronously
HRESULT hr = async_call->Finish_SomeMethod();
/* final result, immediate: hr == RPC_E_SERVERCALL_RETRYLATER */
I am using JNA to access User32 functions (I dont think it has got to do with Java here, more of concept problem). In my application, I have a Java process which communicates with the Canon SDK. To dispatch any messages I am using the below function:
private void peekMessage(WinUser.MSG msg) throws InterruptedException {
int hasMessage = lib.GetMessage(msg, null, 0, 0);
if (hasMessage != 0) {
lib.TranslateMessage(msg);
lib.DispatchMessage(msg);
}
Thread.sleep(1);
}
peekMessage is called in a loop and it all works well. Whenever an Image is taken from camera, I get the event and do the rest.
But I have observed, say after about 15 seconds (sometimes never or sometimes just at start) of no activity with camera, taking picture does not give me any download event. Later the whole application becomes unusable as it doesn't get any events from camera.
What can be the reason for this? Please let me know of any other info needed, I can paste the respective code along.
Edit:
Initialization:
Map<String, Integer> options = new HashMap<String, Integer>();
lib = User32.INSTANCE;
hMod = Kernel32.INSTANCE.GetModuleHandle("");
options.put(Library.OPTION_CALLING_CONVENTION, StdCallLibrary.STDCALL_CONVENTION);
this.EDSDK = (EdSdkLibrary) Native.loadLibrary("EDSDK/dll/EDSDK.dll", EdSdkLibrary.class, options);
private void runNow() throws InterruptedException {
while (!Thread.currentThread().isInterrupted()) {
Task task = queue.poll();
if (task != null) {
int taskResult = task.call();
switch (taskResult) {
case (Task.INITIALIZE_STATE):
break;
case (Task.PROCESS_STATE):
break;
case (Task.TERMINATE_STATE): {
//queue.add(new InitializeTask());
Thread.currentThread().interrupt();
break;
}
default:
;
}
}
getOSEvents();
}
}
WinUser.MSG msg = new WinUser.MSG();
private void getOSEvents() throws InterruptedException {
if (isMac) {
receiveEvents();
} else {
peekMessage(msg);
}
}
Above, whenever I get my camera event, it add's it to the queue and in each loop I check the queue to process any Task. One more important information: This is a process running on cmd and has no window. I just need the events from my camera and nothing else.
The code where I register callback functions:
/**
* Adds handlers.
*/
private void addHandlers() {
EdSdkLibrary.EdsVoid context = new EdSdkLibrary.EdsVoid(new Pointer(0));
int result = EDSDK.EdsSetObjectEventHandler(edsCamera, new NativeLong(EdSdkLibrary.kEdsObjectEvent_All), new ObjectEventHandler(), context).intValue();
//above ObjectEventHandler contains a function "apply" which is set as callback function
context = new EdSdkLibrary.EdsVoid(new Pointer(0));
result = EDSDK.EdsSetCameraStateEventHandler(edsCamera, new NativeLong(EdSdkLibrary.kEdsStateEvent_All), new StateEventHandler(), context).intValue();
//above StateEventHandler contains a function "apply" which is set as callback function
context = new EdSdkLibrary.EdsVoid(new Pointer(0));
result = EDSDK.EdsSetPropertyEventHandler(edsCamera, new NativeLong(EdSdkLibrary.kEdsStateEvent_All), new PropertyEventHandler(), context).intValue();
//above PropertyEventHandler contains a function "apply" which is set as callback function
}
You are getting ALL messages from ALL windows that belong to this thread, that includes all mouse moves, paints etc. if you aren't rapidly calling this function your message queue will overflow and cause the behavior you describe.
The sleep you definitely don't want as GetMessage yields if no message is waiting.
So if there exists a normal message pump(s) (i.e GetMessage/DispatchMessage) loop somewhere else for this threads window(s) then you should let that pump do most of the work, perhaps use wMsgFilterMin, wMsgFilterMax to just get the event message you require; or even better in this case use peekmessage with PM_NOREMOVE (then you will need your sleep
call as peekmessage returns immediately).
Alternatively provide the hWnd of the window that generates the event to reduce the workload.
Use spy++ to look into which windows this thread owns and what messages are being produced.
To take this answer further please provide answers to: what else is this thread doing and what windows does it own; also is this message pump the only one or do you call into the SDK API where it may be pumping messages too?
There is an OpenSource project wrapping EDSDK with JNA and it has a version of your code that is probably working better:
https://github.com/kritzikratzi/edsdk4j/blob/master/src/edsdk/api/CanonCamera.java#L436
Unfortunately this is not platform independent and specifically the way things work on windows. I am currently in the process of trying to get a MacOS version of things working at:
https://github.com/WolfgangFahl/edsdk4j
I have block driver for a hot-pluggable PCI storage device. if the device is removed during IO, I never seem to get a call to release (i.e. mydev_blk_release(struct gendisk *gd, fmode_t mode)), which I think is preventing del_gendisk() from completing, thus hanging the cleanup of the driver. I am ending all requests on the queue once an eject happens, but it still doesn't seem to cause a release. What is the right way to terminate requests and delete the gendisk in the case of vanished media?
This is caused by not ending the request that is broken by the device removal. In my driver, I had the folowing request_fn:
static void mydev_submit_req(struct request_queue *q)
{
struct mydev_info *mydev = q->queuedata;
if (!mydev){
struct request* req;
while ((req = blk_fetch_request(q)) != NULL){
req->cmd_flags |= REQ_QUIET;
__blk_end_request_all(req, -ENODEV);
}
} else {
queue_work(mydev->wq, &mydev->work);
}
}
This will prevent the requests entering the driver's workqueue when the device disappears (signified by the loss of mydev). However this hung because the last request was not actually completed, causing q->rq->elvpriv (now called q->nr_rqs_elvpriv) to remain at 1, which caused blk_drain_queue() to spin forever, which hung blk_cleanup_queue() and prevented the driver being able to remove the device.
The solution looks like this (in the workqueue callback function in my driver, but this depends on how you structure the IO work):
req = blk_fetch_request(q);
while (req) {
// returns -ENODEV if the disk is ejected during transfer
//bytes tells us how many bytes we managed to do
res = mydev_do_req(q, req, &bytes);
if (unlikely(res == -ENODEV)) {
dev_err(&mydev->pdev->dev,
"device ejected during transfer, returning\n");
//end the current request, since we started it
//THIS IS WHAT WAS MISSING
__blk_end_request_all(req, -ENODEV);
break;
//get out - the rest of the queue will be emptied on the next
//submit_req
} else if (!__blk_end_request(req, res, bytes)) {
req = blk_fetch_request(q); //get the next request
}
}
I am trying to write a function which, given a number of seconds and a callback, runs the callback after the given number of seconds. The callback does not have to be on the same thread. The target language is C++/CX.
I tried using Windows::System::Threading::ThreadPoolTimer, but the result is a memory access exception. The issue appears to be that the callback implementation (in native C++) can't be accessed from the managed thread that the timer is running its callback on.
ref class TimerDoneCallback {
private:
function<void(void)> m_callback;
public:
void EventCallback(ThreadPoolTimer^ timer) {
m_callback(); // <-- memory exception here
}
TimerDoneCallback(function<void(void)> callback) : m_callback(callback) {}
};
void RealTimeDelayCall(const TimeSpan& duration, function<void(void)> callback) {
auto t = ref new TimerDoneCallback(callback);
auto e = ref new TimerElapsedHandler(t, &TimerDoneCallback::EventCallback);
ThreadPoolTimer::CreateTimer(e, duration);
}
void Test() {
RealTimeDelayCall(duration, [](){}); //after a delay, run 'do nothing'
}
I don't want to create a thread and sleep on it, because there may be many concurrent delays.
The TimerDoneCallback instance is not kept alive - delegates in C++/CX take weak references to the target object (to avoid circular references). You can override this behavior by using the extended overload of the delegate constructor:
auto e = ref new TimerElapsedHandler(t, &TimerDoneCallback::EventCallback, CallbackContext::Any, true);
The final bool parameter should be true for strong references, and false for weak references. (False is the default.)
You could also consider using the timer class in PPL agents to make a delayed callback: http://msdn.microsoft.com/en-us/library/hh873170(v=vs.110).aspx to avoid needing to use ThreadPoolTimer.
I'm using CGEventTapCreate to "steal" media keys from iTunes when my app is running. The code inside of the callback that I pass to CGEventTapCreate examines the event, and if it finds that it's one of the media keys, posts an appropriate notification to the default notification center.
Now, this works fine if I post a notification for the "key up" event. If I do that for "key down" events, eventually my app stops getting media key events and iTunes takes over. Any ideas on what can be causing this? The relevant part of the code is below
enum {
...
PlayPauseKeyDown = 0x100A00,
PlayPauseKeyUp = 0x100B00,
...
};
static CGEventRef event_tap_callback(CGEventTapProxy proxy,
CGEventType type,
CGEventRef event,
void *refcon)
{
if (!(type == NX_SYSDEFINED) || (type == NX_KEYUP) || (type == NX_KEYDOWN))
return event;
NSEvent* keyEvent = [NSEvent eventWithCGEvent: event];
if (keyEvent.type != NSSystemDefined) return event;
switch(keyEvent.data1)
{
case PlayPauseKeyUp: // <--- this works reliably
//case PlayPauseKeyDown: // <--- this will break eventually
post_notification(#"PlayPauseMediaKeyPressed", nil, nil);
return NULL;
... and so on ...
Does something kill my event tap if the callback takes too long?
Some people suspect that Snow Leopard has a bug that sometimes disables event taps even if they don't take too long. To handle that, you can watch for the event type kCGEventTapDisabledByTimeout, and respond by re-enabling your tap with CGEventTapEnable.
First of all, why is your first "if" allowing key-down and key-up events to pass? Your second "if" only lets system events pass through anyway. So for all key-down/-up events you create a NSEvent, just to drop the event one line further downwards. That makes little sense. An Event Tap should always be as fast as possible, otherwise it will slow down all event processing of the whole system. Your callback should not even be called for key-down/-up events, since system events are not key-down/-up events, they are system events. If they were key events, you would for sure never access data1, but instead use the "type" and "keyCode" methods to get the relevant information from them.
static CGEventRef event_tap_callback(CGEventTapProxy proxy,
CGEventType type,
CGEventRef event,
void *refcon)
{
NSEvent * sysEvent;
// No event we care for? return ASAP
if (type != NX_SYSDEFINED) return event;
sysEvent = [NSEvent eventWithCGEvent:event];
// No need to test event type, we know it is NSSystemDefined,
// becuase that is the same as NX_SYSDEFINED
Also you cannot determine if that is the right kind of event by just looking at the data, you must also verify the subtype, that must be 8 for this kind of event:
if ([sysEvent subtype] != 8) return event;
The next logical step is to split the data up into its components:
int data = [sysEvent data1];
int keyCode = (data & 0xFFFF0000) >> 16;
int keyFlags = (data & 0xFFFF);
int keyState = (keyFlags & 0xFF00) >> 8;
BOOL keyIsRepeat = (keyFlags & 0x1) > 0;
And you probably don't care for repeating key events (that is when I keep the key pressed and it keeps sending the same event over and over again).
// You probably won't care for repeating events
if (keyIsRepeat) return event;
Finally you should not define any own constant, the system has ready to use constants for those keys:
// Analyze the key
switch (keyCode) {
case NX_KEYTYPE_PLAY:
// Play/Pause key
if (keyState == 0x0A) {
// Key down
// ...do your stuff here...
return NULL;
} else if (keyState == 0x0B) {
// Key Up
// ...do your stuff here...
return NULL;
}
// If neither down nor up, we don't know
// what it is and better ignore it
break;
case NX_KEYTYPE_FAST:
// (Fast) Forward
break;
case NX_KEYTYPE_REWIND:
// Rewind key
break;
}
// If we get here, we have not handled
// the event and want system to handle it
return event;
}
And if this still not works, my next question would be what your post_notification function looks like and do you also see the described problem if you don't call post_notification there, but just make a NSLog call about the event you just saw?
In your handler, check for the following type, and just re-enable the listener.
if (type == kCGEventTapDisabledByTimeout) {
NSLog(#"Event Taps Disabled! Re-enabling");
CGEventTapEnable(eventTap, true);
return event;
}