2

I know that when WSARecv is used with it may finishes immediately and in such case a completion packet will still be posted and this behavior can be altered using SetFileCompletionNotificationModes

but I want to know the case for files and pipes with WriteFile , if I used iocp to make async reads and writes and an operation has finished immediately will the same behavior take place ? or I have to handle this ?

dev65
  • 1,440
  • 10
  • 25
  • no any difference between `WSARecv` or `WriteFile` here. both is asynchronous i/o api – RbMm Nov 22 '19 at 22:26

2 Answers2

2

Per Why does my asynchronous I/O request return TRUE instead of failing with ERROR_IO_PENDING?:

When you specify FILE_FLAG_OVERLAPPED, you’re promising that your program knows how to handle I/O which completes asynchronously, but it does not require the I/O stack to behave asynchronously. A driver can choose to perform your I/O synchronously anyway. For example, if the write operation can be performed by writing to cache without blocking, the driver will just copy the data to the cache and indicate synchronous completion. Don’t worry, be happy: Your I/O completed even faster than you expected!

Even though the I/O completed synchronously, all the asynchronous completion notification machinery is still active. It’s just that they all accomplished their job before the Write­File call returned. This means that the event handle will still be signaled, the completion routine will still run (once you wait alertably), and if the handle is bound to an I/O completion port, the I/O completion port will receive a completion notification.

You can use the Set­File­Completion­Notification­Modes function to change some aspects of this behavior, giving some control of the behavior of the I/O subsystem when a potentially-asynchronous I/O request completes synchronously.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • thanks . This includes all asynchronous apis including ConnectNamedPipe , right ? – dev65 Nov 23 '19 at 04:27
  • I mean if ConnectNamedPipe returned FALSE and GetLastError() returned ERROR_PIPE_CONNECTED will a completion notification be posted ? – dev65 Nov 23 '19 at 11:42
  • @dev65 - yes, will be. this related to **any** asynchronous api on file binded to some iocp in case we pass not zero pointer to context – RbMm Nov 23 '19 at 17:19
  • @Remy but from the example at https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipe-server-using-overlapped-i-o they signal an event when ERROR_PIPE_CONNECTED is returned – dev65 Nov 30 '19 at 09:45
  • @dev65 per that example: "*The state of the event object is not changed if the operation finishes before the function returns.*" - I don't know if that is true or not, I don't use Overlapped I/O very often. Seems to contradict what Raymond says. So you will just have to try it for yourself and see what really happens. – Remy Lebeau Nov 30 '19 at 17:00
  • @dev65 - *I mean if ConnectNamedPipe returned FALSE and GetLastError() returned ERROR_PIPE_CONNECTED will a completion notification be posted ?* - in this case will be no notification. notification will be if api return pending status or success status. in case error status - will be not – RbMm Dec 26 '19 at 16:19
  • @RbMm I have already tried it : https://social.msdn.microsoft.com/Forums/en-US/94bdd003-a10a-4d6e-9221-514794f01ab7/will-i-receive-iocp-notification-from-connectnamedpipe-when-it-returns-0-and-getlasterror-returns?forum=windowsgeneraldevelopmentissues – dev65 Dec 26 '19 at 20:25
  • @dev65 - exist general rule for all asynchronous I/O api. i know this topic very well. if api call return error status - so call completed synchronous with error - no packet will be queued to iocp. this is not about concrete api and status. this is for all – RbMm Dec 26 '19 at 20:37
  • @dev65 - if want general knowledge - https://pastebin.com/HGD4BrHM – RbMm Dec 26 '19 at 21:24
  • @RbMm that seems to be in direct conflict with what Raymond Chen wrote, though. – Remy Lebeau Dec 27 '19 at 02:34
  • @RemyLebeau - what you more concrete mean under conflict ? the Raymond Chen not wrote about when notification will be and not. nothing say about error case. however i perfect know this topic. if error from I/O manager (due invalid arguments/handles, align, insuffient resourses) - no notification. otherwise request will be sent to driver. if driver return `NT_ERROR` code ( [c0000000, FFFFFFFF) range) will be no notification, otherwise will be (`Set­File­Completion­Notification­Modes` can prevent on synchronous success completion post notification) – RbMm Dec 27 '19 at 02:52
  • but even in case error status can be completion notifications (if fast io used, it return true with error status). only correct solution which i know - need check iosb (overlapped) after I/O completed synchronous - are it modified. notification will be when and only when iosb modified. but because iosb can be accessed in concurrent from 2 threads (after api call and from callback) - need use reference count on it, for correct deletion. example when will be notification on error - call `LockFileEx` on folder (here fast io lock used, folder is invalid for lock). – RbMm Dec 27 '19 at 17:05
  • and documentation everywhere wrong for this question - [SetFileCompletionNotificationModes](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setfilecompletionnotificationmodes) *A request returns **success** immediately without returning ERROR_PENDING* - here **success** unnecessary word. – RbMm Dec 27 '19 at 17:05
  • [CancelThreadpoolIo](https://learn.microsoft.com/en-us/windows/win32/api/threadpoolapiset/nf-threadpoolapiset-cancelthreadpoolio) *An overlapped (asynchronous) I/O operation fails (that is, the asynchronous I/O function call returns failure with an error code other than ERROR_IO_PENDING).* again exist rarely case I/O fail but will be notification, as in case `LockFileEx`- so not need call `CancelThreadpoolIo` in this case. simply demo - https://pastebin.com/qWrMYvy4 . may be even Raymond Chen dont know this, but i not sure that this topic interesting for somebody – RbMm Dec 27 '19 at 17:06
1

exist common behavior for all asynchronous api, it implicit described in CancelThreadpoolIo function

note, by design we need call CancelThreadpoolIo when and only when will not notify to the I/O completion port and the associated I/O callback function will not be called.

you must call the CancelThreadpoolIo function for either of the following scenarios:

  • An overlapped (asynchronous) I/O operation fails (that is, the asynchronous I/O function call returns failure with an error code
    other than ERROR_IO_PENDING).
  • An asynchronous I/O operation returns immediately with success and the file handle associated with the I/O completion object has the
    notification mode FILE_SKIP_COMPLETION_PORT_ON_SUCCESS. The file
    handle will not notify the I/O completion port and the associated I/O callback function will not be called.

so let dwErrorCode error code returned by api (NOERROR if win32 api return TRUE)

the next function say you - will be or not notify to IOCP

bool IsWillBeNotification(ULONG dwErrorCode, BOOL bSkipCompletionPortMode)
{
    switch (dwErrorCode)
    {
    case ERROR_IO_PENDING:
        return true;
    case NOERROR:
        return !bSkipCompletionPortMode;
    default:
        return false;
    }
}

in case we use native API and NTSTATUS

bool IsWillBeNotification(NTSTATUS status, BOOL bSkipCompletionPortMode)
{
    return (status == STATUS_PENDING) || (!NT_ERROR(status) && !bSkipCompletionPortMode);
}

so:

  • if STATUS_PENDING - will be IOCP packet
  • if NT_ERROR(status) - will be no packet (status in range [0xC0000000, 0xFFFFFFFF] )
  • otherwise based on bSkipCompletionPortMode - will be if it not set

note that this is general rule for any asynchronous io api. only NtLockFile/LockFileEx - exception from this rule - can be IOCP notification even if api just fail, due to error inside NtLockFile implementation

RbMm
  • 31,280
  • 3
  • 35
  • 56