#ifndef __INotify_h__ # define __INotify_h__ #include "Socket.h" #include #include namespace core { class INotify : Socket { public: INotify(EPoll &ePoll); ~INotify(); int addWatch(coreutils::ZString &watch); void removeWatch(int wd); void onDataReceived(coreutils::ZString &data) override; virtual void inAccess(coreutils::ZString name) {} virtual void inAttrib(std::string name) {} virtual void inCloseWrite(std::string name) {} virtual void inCloseNoWrite(std::string name) {} virtual void inCreate(coreutils::ZString &name) {} virtual void inDelete(std::string name) {} virtual void inDeleteSelf(std::string name) {} virtual void inModify(std::string name) {} virtual void inMoveSelf(std::string name) {} virtual void inMovedFrom(std::string name) {} virtual void inMovedTo(std::string name) {} virtual void inOpen(std::string name) {} /// core::INotify is a long-lived Socket subclass that is neither /// a TCPSession (shared_ptr/pin()-owned) nor a listening /// TCPServer - it is normally embedded as a base subobject of a /// server object constructed once in main() and living for the /// whole process (e.g. mail::SMTPServer's queue-directory watch). /// Thread::run()'s epoll dispatch only ever recognized those two /// categories of raw pointer as safe to call directly (see /// TCPServer::isKnownListeningSocket()'s own doc comment) - /// anything else fell through to the "stale/unrecognized epoll /// event" branch and was silently dropped forever. Confirmed /// live: a real IN_CREATE event on a mail queue directory logged /// exactly that "Ignoring stale/unrecognized epoll event" line /// and the newly queued message was never delivered - it just sat /// in the queue until the next process restart, whose /// processExisting() directory scan (a plain synchronous loop, /// entirely independent of epoll) happened to flush the backlog /// and made the bug look intermittent. Registering the instance here, /// mirroring listeningSockets() exactly, gives Thread::run() the /// same kind of safe "yes, dispatch to this raw pointer directly" /// signal for INotify objects too. static bool isKnownINotify(void *ptr) { std::lock_guard guard(knownINotifiesMutex()); return knownINotifies().count(ptr) > 0; } private: static std::mutex &knownINotifiesMutex() { static std::mutex m; return m; } static std::set &knownINotifies() { static std::set s; return s; } }; } #endif