Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why can't I reuse an event even after explicit ResetEvent call?

I want to watch for changes done with a file (the event i’m waiting for is change contents event, i.e. last modified date is updated)

I have a code like this (minimalized example of actual code)
I expect that each iteration of the while loop the event gets reset and is available to be fired again but that doesn’t happen
Why it fires change event only once?

int main()
{
    const wchar_t *dir_path = L"C:\\Users\\IC\\AppData\\Roaming\\JetBrains\\CLion2021.3\\scratches\\";

    HANDLE hDir = ::CreateFileW(
        dir_path,
        FILE_LIST_DIRECTORY,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
        NULL
    );

    FILE_NOTIFY_INFORMATION fni;
    OVERLAPPED overlapped;
    overlapped.hEvent = ::CreateEventA(NULL, FALSE, FALSE, NULL);

    ::ReadDirectoryChangesW(
        hDir,
        &fni,
        sizeof(fni),
        TRUE,
        FILE_NOTIFY_CHANGE_LAST_WRITE,
        NULL,
        &overlapped,
        NULL
    );

    while (true)
    {
        std::vector<HANDLE> all_job_event_handles;
        if (::ResetEvent(overlapped.hEvent) == FALSE)
        {
            printf("ResetEvent failed\n");
            fflush(stdout);
            return 1;
        }
        all_job_event_handles.push_back(overlapped.hEvent);

        DWORD result = ::WaitForMultipleObjects(all_job_event_handles.size(), all_job_event_handles.data(), FALSE, INFINITE);
        if (result == WAIT_FAILED)
        {
            printf("WaitForMultipleObjects failed\n");
            fflush(stdout);
            return 1;
        }

        if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + all_job_event_handles.size())
        {
            printf("file changed\n");
            fflush(stdout);
        }
    }
}

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Because that’s just not how ReadDirectoryChanges works. It doesn’t continuously send you changes. It sends you one batch of changes. You process them. You call the function again to tell the system that you want more changes.

I found a correct usage example of the function here: https://gist.github.com/nickav/a57009d4fcc3b527ed0f5c9cf30618f8

Some side notes:

  • You don’t check whether ReadDirectoryChanges succeeds. This is bad; if it failed, you will hang on the Wait call forever.
  • You don’t zero-initialize the OVERLAPPED structure.
  • You create the event as an auto-reset event (second parameter is FALSE). ResetEvent on such an event does nothing.
  • All the event handles you add into your vector are the same event object. You just have an ever-growing list of the same event repeatedly that you pass to WaitForMultipleObjects. This does nothing at best, but will eventually fail because WFMO doesn’t allow more than MAXIMUM_WAIT_OBJECTS handles, and this number is fairly low (32, I think).
  • You probably want a more permissive share mode on the directory you open.
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading