Jump to content

Waiting For Multiple Objects (win32)

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
12 replies to this topic

#1
innerLOL

innerLOL

    Newbie

  • Members
  • PipPip
  • 29 posts
i want to accomplish:
download manager, simultane~ download of many files.

i dont want to go by 1 handle = 1 blocking thread because its a waste.


there is function WaitForMultipleObjects()
but i cant kill handle on timeout.

i have XX handles idle, and only 1 active (signaled in time < timeout).
Function have no way of flushing out idle handles because 1 is returning, and i cant put there more handles. Thats obvious DoS bug.

How do i avoid it?
I want WaitForMultipleObjects(), but returning in 2 cases:
handle signaled, or timeout passed for EACH handle. if signaled - handle it, if timeout - free space.



Help me please..

#2
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,721 posts
WaitForMultipleObjectsEx Function (Windows)
sudo rm -rf /

#3
innerLOL

innerLOL

    Newbie

  • Members
  • PipPip
  • 29 posts
ok but it doesnt solve my problem, how do i kill handle wich is stuck?

#4
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,721 posts

Quote

i have XX handles idle, and only 1 active (signaled in time < timeout).
Function have no way of flushing out idle handles because 1 is returning, and i cant put there more handles. Thats obvious DoS bug.
Are you sure you want to do it this way? It seems somewhat inefficient. If you had all threads running concurrently, then that'd be a different thing. But since you only have one running at once, this seems to be a design flaw.
sudo rm -rf /

#5
innerLOL

innerLOL

    Newbie

  • Members
  • PipPip
  • 29 posts
what are you proposing then?

i just want to avoid thread waiting for i/o completion doing nothing.

#6
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,721 posts
Oooh, I/O completion. That makes much more sense. Here's what you need to do: You're going need to do asynchronous file IO, using ReadFile and/or WriteFile and an OVERLAPPED structure. The OVERLAPPED structure is as follows:

typedef struct _OVERLAPPED
{
    ULONG_PTR Internal;
    ULONG_PTR InternalHigh;
    union
    {
        struct 
        {
            DWORD Offset;
            DWORD OffsetHigh;
        } ;

        PVOID Pointer;
    } ;

    HANDLE    hEvent;
}OVERLAPPED;
The Offset and OffsetHigh members tell Windows the byte position within the file / device that you want to read from or write to. Pointer must be zero.
For hEvent, you're going to want to call CreateEvent and set hEvent to the returned handle. Make sure the event starts in a non-signaled state and use a manual reset for file IO.
Because ReadFile and WriteFile will perform their operations asynchronously, you can call them repeatedly without having to wait for them to finish. After starting all the operations, call Sleep with your specified timeout period, then iterate through all your events and check to see which ones are signaled using the HasOverlappedIoCompleted macro. If any are still running (i.e. HasOverlappedIoCompleted returns false, kill the IO using CancelIo.

Here's a sample of what I mean.
HANDLE hFiles[NUM_FILES];
HANDLE hIoEvents[NUM_FILES];
OVERLAPPED olOverlappedFiles[NUM_FILES];
BYTE bFileBuffers[NUM_FILES][BUFFER_SIZE];
DWORD dwBytesRead[NUM_FILES];

/*I'm assuming you've already opened all the files*/
memset(olOverlappedFiles, 0, sizeof(OVERLAPPED) * NUM_FILES);

olOverlappedFiles[0].Offset = /*blah*/;
olOverlappedFiles[0].OffsetHigh = /*whatever*/;
olOverlappedFiles[0].hEvent = CreateEvent(NULL, TRUE, FALSE, "ASYNCHIO_0");
.
.
.
for(int i = 0; i < NUM_FILES; ++i)
    ReadFile(hFiles[i], bFilesBuffers[i], BUFFER_SIZE, &dwBytesRead[i], &olOverlappedFiles[i]);

Sleep(TIMEOUT_PERIOD);

for(int i = 0; i < NUM_FILES; ++i)
{
    if(!HasOverlappedIoCompleted(&olOverlappedFiles[i]))
        CancelIo(hFiles[i]);
    CloseHandle(hEvents[i]);
    CloseHandle(hFiles[i]);
}

Edited by dargueta, 25 December 2009 - 08:20 AM.
Added links

sudo rm -rf /

#7
innerLOL

innerLOL

    Newbie

  • Members
  • PipPip
  • 29 posts
well i think its a bad idea.

Why would i call Sleep? It will just slow down my app, i use Sleep only for debugging purposes, i dont think it was designed to do something else.

Perhaps WaitForMultipleObjects() with bWaitAll set to TRUE and my timeout.
After timeout passes, i loop with GetOverlappedResult()/GetLastError() to check wich are completed, and discard rest. If WFMO() dont return timeout, i wont have to loop because i know all descriptors are alive.


thx for help anyway

#8
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,721 posts

Quote

Perhaps WaitForMultipleObjects() with bWaitAll set to TRUE and my timeout.
After timeout passes, i loop with GetOverlappedResult()/GetLastError() to check wich are completed, and discard rest. If WFMO() dont return timeout, i wont have to loop because i know all descriptors are alive.
Forgot about WaitForMultipleObjects. Good catch. :)
Just in case you didn't know, HasOverlappedIoCompleted is just a macro of GetOverlappedResult. The number of bytes written/read are stored in the InternalHigh field of your OVERLAPPED struct and the error code is in Internal, so really you won't need GetLastError (which won't give you sufficient information if more than one fails) or HasOverlappedIoCompleted. HasOverlappedIoCompleted won't get you the error code of individual IO operations, nor will GetLastError.
sudo rm -rf /

#9
innerLOL

innerLOL

    Newbie

  • Members
  • PipPip
  • 29 posts
this is also bad idea...

if 1 descriptor will be 'dead' everytime all other will wait full timeout.
afff........

know what? i ownt give any timeout.
bwaitall = false, and i will manually discard desciptors. this cant be automated, because readifle might wait few days before read data from pipe, for example.

my knowleadge has huge gaps, need to fix it.

#10
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,721 posts
You really don't like anything I have to say, do you?

Quote

because readifle might wait few days before read data from pipe, for example.
Where'd you get that from? Care to cite?
sudo rm -rf /

#11
innerLOL

innerLOL

    Newbie

  • Members
  • PipPip
  • 29 posts
now i know that there is no way not to say if io operation is still pending or died.


inside system everything return a value. io cant be pending forever, if handle was closed - i get error, if calceled - else error.


timeout apply only to sockets, have so_rcv/snd timeo, and i will test it to see if WFMO() fail or not.
if should as soon as 1 handle is destroyed.

#12
innerLOL

innerLOL

    Newbie

  • Members
  • PipPip
  • 29 posts
1 more question, can i CloseHandle() without ensuring that pending io was canceled?
i know it will work, but is it documented way, or not?