@@ -22,6 +22,7 @@ class FileWatcherService {
2222 private:
2323#if defined(_WIN32)
2424 HANDLE dir_handle;
25+ HANDLE stop_event;
2526#elif defined(__APPLE__)
2627 FSEventStreamRef event_stream;
2728#else // Linux
@@ -37,10 +38,16 @@ class FileWatcherService {
3738 if (!std::filesystem::exists (path)) {
3839 throw std::runtime_error (" Path does not exist: " + path);
3940 }
41+ #ifdef _WIN32
42+ stop_event = CreateEvent (NULL , TRUE , FALSE , NULL );
43+ #endif
4044 CTL_INF (" FileWatcherService created: " + path);
4145 }
4246
43- ~FileWatcherService () { stop (); }
47+ ~FileWatcherService () {
48+ CTL_INF (" FileWatcherService destructor" );
49+ stop ();
50+ }
4451
4552 void start () {
4653 if (running_) {
@@ -52,16 +59,44 @@ class FileWatcherService {
5259 }
5360
5461 void stop () {
62+ if (!running_) {
63+ return ;
64+ }
65+
5566 running_ = false ;
67+
68+ #ifdef _WIN32
69+ // Signal the stop event
70+ SetEvent (stop_event);
71+ #elif defined(__APPLE__)
72+ if (event_stream) {
73+ FSEventStreamStop (event_stream);
74+ FSEventStreamInvalidate (event_stream);
75+ }
76+ #else // Linux
77+ // For Linux, closing the fd will interrupt the read() call
78+ if (fd >= 0 ) {
79+ close (fd);
80+ }
81+ #endif
82+
83+ // Add timeout to avoid infinite waiting
5684 if (watch_thread_.joinable ()) {
5785 watch_thread_.join ();
5886 }
5987
6088#ifdef _WIN32
61- CloseHandle (dir_handle);
62- #endif
63-
64- #ifdef Linux
89+ if (stop_event != NULL ) {
90+ CloseHandle (stop_event);
91+ }
92+ if (dir_handle != INVALID_HANDLE_VALUE) {
93+ CloseHandle (dir_handle);
94+ }
95+ #elif defined(__APPLE__)
96+ if (event_stream) {
97+ FSEventStreamRelease (event_stream);
98+ }
99+ #else // Linux
65100 CleanupWatches ();
66101#endif
67102 CTL_INF (" FileWatcherService stopped!" );
@@ -134,7 +169,7 @@ class FileWatcherService {
134169 OVERLAPPED overlapped = {0 };
135170 overlapped.hEvent = CreateEvent (NULL , TRUE , FALSE , NULL );
136171 DWORD bytesReturned;
137-
172+ HANDLE events[] = {overlapped. hEvent , stop_event};
138173 while (running_) {
139174 if (!ReadDirectoryChangesW (
140175 dir_handle, buffer, sizeof (buffer), TRUE ,
@@ -143,11 +178,14 @@ class FileWatcherService {
143178 break ;
144179 }
145180
146- if (WaitForSingleObject (overlapped.hEvent , INFINITE) != WAIT_OBJECT_0) {
181+ // Wait for either file change event or stop event
182+ DWORD result = WaitForMultipleObjects (2 , events, FALSE , INFINITE);
183+ if (result == WAIT_OBJECT_0 + 1 ) { // stop_event was signaled
147184 break ;
148185 }
149186
150- if (!GetOverlappedResult (dir_handle, &overlapped, &bytesReturned,
187+ if (result != WAIT_OBJECT_0 ||
188+ !GetOverlappedResult (dir_handle, &overlapped, &bytesReturned,
151189 FALSE )) {
152190 break ;
153191 }
0 commit comments