Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make shutdown faster in case of a long running event handler #2

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

kovbal
Copy link
Contributor

@kovbal kovbal commented Dec 12, 2020

As detailed in issue #1 if changeEvent() takes a long time and new filesystem events keep happening, then the shutdown of the application is delayed.

This PR solves that problem by not processing entirely these events during shutdown.

The event loop did not close until every filesystem change was
processed, and every change restarted the listening. With this commit
when we're shutting down, we do not listen for new changes anymore.
@KevDi
Copy link

KevDi commented Dec 15, 2020

Thanks for that Pull Request. I tried it out but found another Problem (Sorry for that 😊).
If i know make the same steps as described in the Issue I end up waiting for the Program to close.
Now the Problem seems to stuck here:

while(hasPending() && (res = GetQueuedCompletionStatus(this->iocp.get(), &numOfBytes, &compKey, &ov, INFINITE)) != FALSE) {
   ...

It seems like the FsWatcher contains one WatchInfo with an PendingClose State and then calls GetQueuedCompletionStatus and then waits there forever because no events will be generated and put on the eventqueue as far as i can see.

@KevDi
Copy link

KevDi commented Dec 15, 2020

I did some further analysis to this and i think the root of the lies in the processEvent Function.
If the application is stopped but there are still files added to the directory the Number of Bytes transferred is not equal to zero so the WatchInfo is not ereased from the Map.
Inside the While Loop it's still pending but could not be closed because the Directory Handle is invalid.

@KevDi
Copy link

KevDi commented Dec 16, 2020

One Solution which works for me was to change the processEvent Function.

I just have added the following:

void FsWatcher::processEvent(DWORD numberOfBytesTrs, OVERLAPPED* overlapped) {
    ...
    if (this->shuttingDown) {
        watchInfoIt->second.state = WatchInfo::State::PendingClose;
    }
    
    if (watchInfoIt->second.state == WatchInfo::State::Listening) {
    ....
    }
    
    if (numberOfBytes == 0 || this->shuttingDown) {
        if (watchInfoIt->second.state == WatchInfo::State::PendingClose) {
           std::cout << "Erease WatchInfo " << watchInfoIt->second.rId << "\n";
           this->watchInfos.erase(watchInfoIt);
        } else {
           std::cout << "Error: " << GetLastError() << '\n';
           this->errorEvent(watchInfoIt->second.rId);
       }
       return;
    }
    ....
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants