How does WaitForDebugEvent[Ex] report a timeout? - winapi

The WaitForDebugEvent and WaitForDebugEventEx APIs allow a caller to specify a timeout. The functions return when a debug event occurred, or the timeout expired, whichever happened first. While the documentation describes how debug events are reported, there's no information at all on the APIs' behaviors in case of a timeout.
Questions
How do the APIs report a timeout?
Does this protocol hold for a value of 0 for dwMilliseconds as well?

How do the APIs report a timeout?
The function returns FALSE and sets the last error to ERROR_SEM_TIMEOUT(0x79).
Does this protocol hold for a value of 0 for dwMilliseconds as well?
Yes.
Since it's not documented we'll go with the implementation (I'm on Win 10).
Both kernelbase!WaitForDebugEvent and kernelbase!WaitForDebugEventEx APIs call the same piece of code (simply with a different arg).
In the shared piece of code the second call is made on ntdll!DbgUiWaitStateChange which itself is a simple wrapper around ntdll!NtWaitForDebugEvent.
On function return the code checks if the returned status is either STATUS_ALERTED (0x101) or STATUS_USER_APC (0xc0). If it is, it keeps calling the previous function (ntdll!DbgUiWaitStateChange), otherwise it checks if the status is an error (more precisely if the status is signed).
If it's not signed it checks that the status is STATUS_TIMEOUT (0x102). If it is, the NT Status is converted to a win32 error - from STATUS_TIMEOUT to ERROR_SEM_TIMEOUT (0x79) - and the function is exited.
Inside nt!NtWaitForDebugEvent (kernel level) we can have a good overview of what is happening with the ReactOS source code.
After a call to nt!KeWaitForSingleObject on the debug object the code checks (source) what is the status of the call. If it is STATUS_TIMEOUT (which, if I'm not mistaken should happen in case of a 0 timeout), the function bails out and return the current status, which is, as explained above, converted to ERROR_SEM_TIMEOUT in userland.
Status = KeWaitForSingleObject(&DebugObject->EventsPresent,
Executive,
PreviousMode,
Alertable,
Timeout);
if (!NT_SUCCESS(Status) ||
(Status == STATUS_TIMEOUT) ||
(Status == STATUS_ALERTED) ||
(Status == STATUS_USER_APC))
{
/* Break out the wait */
break;

Related

tarantool how to handle lua errors outside the fiber

I am wondering, how can i set callback on fiber error throw.
example:
local fiber = require("fiber")
local status = 0 --in my case stored in db
local function time_consuming()
lua_error
status = 0
end
function external_api_function()
if status == 1 then return "already running" end
status = 1
fiber.create(time_consuming)
return "started"
end
so i want to set status to 0 if time_consuming function falls. Is where any way to catch it?
I think about checking fiber:status on next api visit. Or create a watchdog for fiber, if i want status to be valid. This will work for me, but seems like not the best solution.
There are multiple ways to achieve your goal.
Within your example both fibers (main and time_consuming task) share the same scope - status variable. If you change the value of the status variable in the child fiber, parent fiber will see an update. You can check this using simple snippet:
status = 1
fiber.create(function() status = 0 end)
print(status) -- 0
Now, to catch an exception, use pcall function. It accepts a function as a first argument, calls it and returns status as a first value following one or more function results. There is also xpcall function if you want to analyse the error being caught. It takes error handler as a second argument.
With pcall you may change your time_consuming function like this:
local function time_consuming()
local ok = pcall(function() lua_error end)
if not ok then
status = 0
end
end
and status will successfully updated if lua_error fails.
But usually I consider this as a bad practice. If more fibers share the same state, it may become difficult to maintain due to uncertainty of the order of fiber execution. So for more reliable solution you may want to use interfiber communication primitives aka channels. You will be able to explicitly ask child fiber to tell you its execution status whether it succeed or not using channel:put() and channel:get() function. See documentation for examples.

How can you tell if SendMessage() was successful (message was delivered)?

is it possible to determine if a SendMessage() call was successful and delivered my message to the target window?
The SendMessage() description in the Windows API seems quiet on this and only says the following:
The return value specifies the result of the message processing; it depends on the message sent.
This obviously refers to the fact that the return code reflects the value returned by the wndproc of the target window.
But what will the return code be if the message wasn't delivered at all (e.g. due to access control, or due to the window having been destoroyed in the meantime)? How can I detect such situations?
There is no way to reliably tell, whether a call to SendMessage succeeded or failed. After all, it only has a single return value, and the entire range of values is used. There is no designated error value.
Playing tricks with the calling thread's last error code won't work either. The scheme proposed in this answer (clearing the last error code prior to the call and evaluating it after the call) is brittle. It's easy to see that it can fail, when sending a message to a window owned by the calling thread (as that window's window procedure is at liberty to change the last error any way it sees fit).
It's not quite as well known, that this can also fail when sending a message to a window owned by a different thread. The code suggests, that no intervening API call can happen in the calling thread. Yet in that scenario, SendMessage will also dispatch incoming cross-thread messages (see When can a thread receive window messages?), allowing the thread's last error code to change.
The only option then is to use SendMessageTimeoutW, as that API reports both the result of the call, as well as an error/success indicator. Passing the SMTO_NOTIMEOUTIFNOTHUNG flag makes sure that an arbitrarily chosen timeout will not adversely affect the outcome.
if SendMessage fail, it set last win32 error code, which we can get back via call GetLastError(). and returned error code, in case fail, never will be 0 (NOERROR) despite this is clear not documented. but how detect that SendMessage is fail ? here we can not base on return value. but we can SetLastError(NOERROR) before call SendMessage and check GetLastError() after:
if SendMessage fail - value returned by GetLastError() will be
not 0. (most common in this case ERROR_INVALID_WINDOW_HANDLE or
ERROR_ACCESS_DENIED).
if we still got 0 as last error - this mean that message was
delivered with no error.
however, possible case, when during SendMessage call, some window procedure
in current thread will be called and
code inside window procedure, set last error to non 0 value. so we
get finally not 0 last error, but not because SendMessage fail.
distinguish between these two cases very problematic
-
SetLastError(NOERROR);
LRESULT lr = SendMessageW(hwnd, *, *, *);
ULONG dwErrorCode = GetLastError();
if (dwErrorCode == NOERROR)
{
DbgPrint("message was delivered (%p)\n", lr);
}
else
{
DbgPrint("fail with %u error\n", dwErrorCode);
}

SendMessage - strange return values

I have an application which uses a three helper threads to read from a database (3 different tables, ~160,000 rows in total), create objects from those rows, then add the objects to one of two lists, depending on what type of object was created. The helper threads add objects to the list through a SendMessage call so that the main thread is the only object adding/removing to/from the list.
The odd thing is that SendMessage doesn't always succeed, I'll frequently get these two errors ERROR_ALREADY_EXISTS (183) and ERROR_TRUSTED_DOMAIN_FAILURE (1788). The function that SendMessage calls just adds an object to the list, and this function always returns success (0). There's no creating files (as ERROR_ALREADY_EXISTS seems to suggest) and there's no network calls so I'm not sure why I'm getting ERROR_TRUSTED_DOMAIN_FAILURE errors.
Any ideas on what might be causing these errors or any way to debug these errors?
As a note, before it was SendMessage I was using PostMessage and would get lots of ERROR_NOT_ENOUGH_QUOTA errors; SendMessage makes the utility work a lot better.
SendMessage() returns the result of the message that is sent. It is up to the message handler to decide what value is actually returned by SendMessage() to the sending code. GetLastError() is only meaningful if SendMessage() itself fails, and you have to use SetLastError() to detect that, eg:
SetLastError(0);
LRESULT res = SendMessage(...);
if ((res == 0) && (GetLastError() != 0))
{
// send failed, for example GetLastError()=ERROR_ACCESS_DENIED if UIPI blocked the message ...
}
else
{
// send succeeded, res is whatever value the message handler returned ...
}
This only works reliably if the target HWND is owned by a different thread than the one that is calling SendMessage(). GetLastError() cannot be influenced across thread boundaries. Any call to SetLastError() within the message handler affects the error code of the HWND's owning thread, not the error code of the sending thread.
However, if the target HWND is owned by the same thread that is calling SendMessage(), and the message handler happens to call SetLastError() (directly, or indirectly via a failed API call) to set a non-zero error code, and happens to return 0 as its result value for SendMessage() to return to the sender, then the only way I can think of for the sender to differentiate whether the error code returned by GetLastError() was set by SendMessage() itself on failure, or set by the message handler, is to use a thread-locale message hook via SetWindowsHookEx() to detect whether the message handler was actually called or not (the only condition I can think of for that happening is if the target HWND is invalid so SendMessage() cannot find its window procedure).
You can use GetWindowThreadProcessId() and GetCurrentThreadId() to check if the target HWND is owned by the calling thread or not.

InternetReadFile() reads data but returns false and sets number of bytes read to zero

Making an asynchronous request with Wininet, when the status callback function is called with INTERNET_STATUS_REQUEST_COMPLETE, I get the http status code.
result = HttpQueryInfo(
this->requestHandle,
HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
&value,
&sizeofDword,
&index);
The status code returned is 200. After that, I call InternetReadFile().
result = InternetReadFile(
this->requestHandle,
((char*)(this->buffer)) + this->totalBytesReceived,
this->bufferSize - this->totalBytesReceived,
&bytesRead);
this->totalBytesReceived += bytesRead;
It returns true and sets lpNumberOfBytesRead to zero. GetLastError() returns ERROR_IO_PENDING, then I wait the callback function is called again with INTERNET_STATUS_REQUEST_COMPLETE.
When that occurs, InternetReadFile() returns true and again sets lpNumberOfBytesRead to zero.
If I debug the application, I can see after the first InternetReadFile() that the response data is already on the lpBuffer. Moreover, if I call Sleep() for one second before InternetReadFile(), InternetReadFile() works correctly.
Sleep(1000);
result = InternetReadFile( ...
Am I missing any step?
I've encountered similar problem, and still the same even using Sleep(1000). I was connecting to a 3rd party camera stream, I've tried it on debug version, which worked perfectly. But when I went back to release version, it just wouldn't work.
I fixed it by changing HttpOpenRequest's lplpszAcceptTypes to NULL, then everything started working to work.
Seems like when WinINet dealing with internet connection, with different type of mobile phone / os /debug or release binary version/ have some kind of different operation which we can not possibly know.

WinSock recv() timeout: setsockopt()-set value + half a second?

I am writing a cross-platform library which, among other things, provides a socket interface, and while running my unit-test suite, I noticed something strange with regard to timeouts set via setsockopt(): On Windows, a blocking recv() call seems to consistently return about half a second (500 ms) later than specified via the SO_RCVTIMEO option.
Is there any explanation for this in the docs I missed? Searching the web, I was only able to find a single other reference to the problem – could somebody who owns »Windows Sockets
Network Programming« by Bob Quinn and Dave Shute look up page 466 for me? Unfortunately, I can only run my test Windows Server 2008 R2 right now, does the same strange behavior exist on other Windows versions as well?
From Networking Programming for Microsoft Windows by Jones and Ohlund:
SO_RCVTIMEO optval
Type: int
Get/Set: Both
Winsock Version: 1+
Description : Gets or sets the timeout value (in milliseconds)
associated with receiving data on the
socket
The SO_RCVTIMEO option sets the
receive timeout value on a blocking
socket. The timeout value is an
integer in milliseconds that indicates
how long a Winsock receive function
should block when attempting to
receive data. If you need to use the
SO_RCVTIMEO option and you use the
WSASocket function to create the
socket, you must specify
WSA_FLAG_OVERLAPPED as part of
WSASocket's dwFlags parameter.
Subsequent calls to any Winsock
receive function (such as recv,
recvfrom, WSARecv, or WSARecvFrom)
block only for the amount of time
specified. If no data arrives within
that time, the call fails with the
error 10060 (WSAETIMEDOUT). If the
receiver operation does time out the
socket is in an indeterminate state
and should not be used.
For performance reasons, this option
was disabled in Windows CE 2.1. If you
attempt to set this option, it is
silently ignored and no failure
returns. Previous versions of Windows
CE do implement this option.
I'd think the crucial information in this is:
If you need to use the SO_RCVTIMEO option and you use the WSASocket
function to create the socket, you
must specify WSA_FLAG_OVERLAPPED as
part of WSASocket's dwFlags parameter
I hope this is still useful :)
I am having the same problem. Going to use
patchedTimeout = max ( unpatchedTimepit - 500, 1 )
Tested this with the unpatchedTimepit == 850
your problem is not in rcv function timeout!
if your application have a while loop to check and receive just put an if statement to check the receive buffer last index for '\0' char to check is the receiving string is ended or not.
typically if rcv function is still receiving return value is the size of received data. size can be used as last index of buffer array.
do{
result = rcv(s,buf,len,0);
if(buf[result] == '\0'){
break;
}
}
while(result > 0);

Resources