Commits

ryanackley committed b69351f

Changed the linux file watcher to use signals to interrupt the call to select instead of a timeout

  • Participants
  • Parent commits 885c8fd

Comments (0)

Files changed (2)

File X11/FileWatcherTaskX11.cpp

 
 
 #include "FileWatcherTaskX11.h"
-#include <boost/thread.hpp>
 #include <sys/inotify.h>
+#include <sys/signal.h>
 #include <iostream>
 #include "variant_list.h"
 
 
 void FileWatcherTaskX11::Watch(boost::filesystem::path p, FB::JSObjectPtr callback)
 {
-	boost::thread thread = boost::thread(boost::bind(&FileWatcherTaskX11::ListenForFileEvents, this, p, callback));
-	thread.detach();
+	thread = boost::thread(boost::bind(&FileWatcherTaskX11::ListenForFileEvents, this, p, callback));
+	//thread.detach();
+}
+
+/* Signal handler that does nothing. This is necessary because
+ * I send a signal to interrupt pselect. Without a signal handler for my signal,
+ * the process will crash. I only care about interrupting the pselect.
+ * */
+static void hdl (int sig)
+{
+	//do nothing
 }
 
 void FileWatcherTaskX11::ListenForFileEvents(boost::filesystem::path path, FB::JSObjectPtr callback)
 	int fd;
 	int wd;
 	char buffer[EVENT_BUF_LEN];
+	sigset_t mask;
+	sigset_t orig_mask;
+	struct sigaction act;
+
+	memset (&act, 0, sizeof(act));
+	act.sa_handler = hdl;
+
+	/* This server should shut down on SIGTERM. */
+	if (sigaction(SIGUSR1, &act, 0)) {
+		std::cerr << ("sigaction");
+		return;
+	}
+
+	sigemptyset (&mask);
+    sigaddset (&mask, SIGUSR1);
+
+    if (sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0) {
+		std::cerr << "sigprocmask";
+		return;
+	}
 
 	/*creating the INOTIFY instance*/
 	fd = inotify_init();
 
 	std::map<int, boost::filesystem::path*> wdMap;
 
-	/*adding the  directory into watch list. Here, the suggestion is to validate the existence of the directory before adding into monitoring list.*/
-	//wd = inotify_add_watch( fd, path.c_str(), IN_MODIFY | IN_MOVED_TO);
 	this->AddWatchToDir(fd, path, wdMap );
 
-	/*read to determine the event change happens on “/tmp” directory. Actually this read blocks until the change event occurs*/
 	while (!this->_ShouldStop())
 	{
 		int i = 0;
 		FD_ZERO(&set);
 		FD_SET(fd, &set);
 
-		int sr = select (FD_SETSIZE, &set, NULL, NULL, &time);
+		int sr = pselect (FD_SETSIZE, &set, NULL, NULL, NULL, &orig_mask);
 		if (!sr) //timeout
 		{
 			continue;
 			break;
 		}
 	}
-	/*removing the “/tmp” directory from the watch list.*/
+	//cleanup
 	std::map<int, boost::filesystem::path*>::iterator it;
 	for (it = wdMap.begin(); it != wdMap.end(); it++)
 	{
 		inotify_rm_watch( fd, (*it).first );
 		delete (*it).second;
 	}
-	//inotify_rm_watch( fd, wd );
 
 	/*closing the INOTIFY instance*/
 	close( fd );
 void FileWatcherTaskX11::StopWatching()
 {
 	this->stop = 1;
+	pthread_kill(thread.native_handle(), SIGUSR1);
+
+	boost::posix_time::time_duration timeout = boost::posix_time::seconds(5);
+	thread.timed_join(timeout);
 }
 
 bool FileWatcherTaskX11::_ShouldStop()
 	return this->stop != 0;
 }
 
+void FileWatcherTaskX11::_SetToStop(int sig)
+{
+	this->stop = 1;
+}
+
 
 
 

File X11/FileWatcherTaskX11.h

 
 #include "JSObject.h"
 #include <boost/filesystem.hpp>
+#include <boost/thread.hpp>
 
 class FileWatcherTaskX11 {
 public:
 	void ListenForFileEvents(boost::filesystem::path path, FB::JSObjectPtr callback);
 	void AddWatchToDir(int fd, boost::filesystem::path path, std::map<int, boost::filesystem::path*> &watchDescriptors);
 	bool _ShouldStop();
+	void _SetToStop(int sig);
 	int stop;
+	boost::thread thread;
 };
 
 #endif /* FILEWATCHERTASKX11_H_ */