Re: callback never invoked
On Sun, Oct 18, 2020 at 02:46:44PM +0500, rustahm wrote: > libev++ to watch a directory of files and call the callback function as > soon as inotify gives at least one relevant event. And I don't want libev++ > to block my main program, that's why I tried to use it with NOWAIT. All event libraries block at least one thread. You coulöd move that into something other than your main thread, but that complicates things so I would not reocmmend that. > Am I doing it totally wrong? Is libev++ a right tool for the task? I am not sure what you are trying to achieve, but libev (not libev++) does kind of impose event-based programming on the user. You could use it differently, but that would be very advanced, and possibly also painful. So if you can't use an event-based approach and do you work in callbacks, libev (or any other event library) would be the wrong tool. > If I add ev_run(EV_A_ 0); to engage_watcher() I get use of undeclared > identifier 'loop'. You cna either use "ev_run (ev_default_loop (), 0)" or, if you have more than one loop, pass the "struct ev_loop *" around. There is also a macro you can use "ev_run (EV_DEFAULT_UC_ 0)" that is faster than calling ev_default_loop if the loop is guartanteed to be initialiased already. > and run the program but it gets blocked until I change a file in the > directory being watched. Yes, that's how it works. You need to cal ev_run in your main program and do your work in callbacks, always returning to the main loop. -- The choice of a Deliantra, the free code+content MORPG -==- _GNU_ http://www.deliantra.net ==-- _ generation ---==---(_)__ __ __ Marc Lehmann --==---/ / _ \/ // /\ \/ / schm...@schmorp.de -=/_/_//_/\_,_/ /_/\_\ ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/mailman/listinfo/libev
Re: callback never invoked
Thank you, Marc, for your input. This is my first time using such a library, so I guess I don't get your point. My main program should only receive a list of relevant events from inotify and process them through a callback function of the main program. I want libev++ to watch a directory of files and call the callback function as soon as inotify gives at least one relevant event. And I don't want libev++ to block my main program, that's why I tried to use it with NOWAIT. Am I doing it totally wrong? Is libev++ a right tool for the task? If I add ev_run(EV_A_ 0); to engage_watcher() I get use of undeclared identifier 'loop'. If I also add ev::default_loop loop; then I can build and run the program but it gets blocked until I change a file in the directory being watched. And even after that the program's window doesn't show up. If I replace 0 with EVRUN_NOWAIT then the window shows up but io_callback() is never invoked again. How can I get it working? On Mon, Oct 12, 2020 at 2:51 PM Marc Lehmann wrote: > On Sun, Oct 11, 2020 at 04:51:09PM +0500, rustahm > wrote: > > Please find attached the source code. Could anyone explain why the > callback > > is never invoked when I do change the files? > > You probably never call ev's mainloop: you only call ev::run once with > NOWAIT, so unless any change happens before that call, libev code is never > invoked and therefore does not have a chance of calling your callback. > > You would need to put something like ev_run (EV_A_ 0) into your main > program > (which you haven't shown). > > Also, ev::get_default_loop() (and .run) is internal undocumented > functionality which you should not call if you want your program to > continue to work with future versions. > > -- > The choice of a Deliantra, the free code+content > MORPG > -==- _GNU_ http://www.deliantra.net > ==-- _ generation > ---==---(_)__ __ __ Marc Lehmann > --==---/ / _ \/ // /\ \/ / schm...@schmorp.de > -=/_/_//_/\_,_/ /_/\_\ > ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/mailman/listinfo/libev
Re: callback never invoked
On Sun, Oct 11, 2020 at 04:51:09PM +0500, rustahm wrote: > Please find attached the source code. Could anyone explain why the callback > is never invoked when I do change the files? You probably never call ev's mainloop: you only call ev::run once with NOWAIT, so unless any change happens before that call, libev code is never invoked and therefore does not have a chance of calling your callback. You would need to put something like ev_run (EV_A_ 0) into your main program (which you haven't shown). Also, ev::get_default_loop() (and .run) is internal undocumented functionality which you should not call if you want your program to continue to work with future versions. -- The choice of a Deliantra, the free code+content MORPG -==- _GNU_ http://www.deliantra.net ==-- _ generation ---==---(_)__ __ __ Marc Lehmann --==---/ / _ \/ // /\ \/ / schm...@schmorp.de -=/_/_//_/\_,_/ /_/\_\ ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/mailman/listinfo/libev
callback never invoked
Hello, Please find attached the source code. Could anyone explain why the callback is never invoked when I do change the files? Thank you, Roustam // custom #include "watcher.h" // standard #include // cross-platform #include // Linux #include #include #include #include std::string dir_path; int file_descriptor, watch_descriptor; ev::io watcher; std::list events; static void io_callback (ev::io &event_watcher, int revents) { events.clear(); char buffer[4096] __attribute__ ((aligned(__alignof__(struct inotify_event; const struct inotify_event *p_file_event; std::size_t event_size = sizeof(struct inotify_event); struct stat metadata; while (true) { ssize_t bytes_count = read(file_descriptor, buffer, sizeof buffer); if (bytes_count == -1) {// no new events to process, exit the loop if (errno != EAGAIN) std::perror("read"); break; } // process new events for (char *p_event = buffer, *end = buffer + bytes_count; p_event < end; p_event += event_size + p_file_event->len) { p_file_event = (const struct inotify_event *) p_event; if (!(p_file_event->mask & IN_ISDIR) && p_file_event->len) {// the file is not a directory and has a name Event file_event; file_event.name = p_file_event->name; if (p_file_event->mask & IN_DELETE || p_file_event->mask & IN_MOVED_FROM)// the file was removed file_event.status = removed; else if(stat((dir_path + '/' + file_event.name).c_str(), &metadata) != -1) {// successfully got file metadata file_event.size = (long long) metadata.st_size; file_event.modified = ctime(&metadata.st_mtime); if (p_file_event->mask & IN_MODIFY || p_file_event->mask & IN_MOVED_TO)// the file was created or modified file_event.status = modified; else// dismiss the event continue; } else// dismiss the event continue; events.push_back(file_event); } } } } std::list engage_watcher(const std::string &directory_path) { std::list result; if (!dir_path.empty()) return result; struct stat metadata; struct dirent *entry = nullptr;// a file // open the directory DIR *directory = nullptr; directory = opendir(directory_path.c_str()); if (directory != nullptr) { dir_path = directory_path; // initialize a file descriptor file_descriptor = inotify_init1(IN_NONBLOCK); if (file_descriptor == -1) { std::perror("inotify_init1"); return result; } // initialize a watch descriptor watch_descriptor = inotify_add_watch(file_descriptor, dir_path.c_str(), IN_MODIFY | IN_MOVED_TO | IN_DELETE | IN_MOVED_FROM); if (watch_descriptor == -1) { std::fprintf(stderr, "Cannot watch the directory. Error: %s\en", std::strerror(errno)); close(file_descriptor); return result;} // iterate through all files in the watched directory while ((entry = readdir(directory))) {// get next file from the watched directory if (entry->d_type != 4) {// the file is not a directory if (stat((dir_path + '/' + entry->d_name).c_str(), &metadata) != -1) {// get file metadata Event file_event; file_event.name = entry->d_name; file_event.size = (long long) metadata.st_size; file_event.modified = ctime(&metadata.st_mtime); file_event.status = modified; result.push_back(file_event); } } } // set the callback for the watcher and start watching watcher.set (); watcher.start(file_descriptor, ev::READ); ev::get_default_loop().run(EVRUN_NOWAIT); } closedir(directory); return result; } void disengage_watcher() { if (dir_path.empty()) return; watcher.stop(); dir_path.clear(); inotify_rm_watch(file_descriptor, watch_descriptor); close(file_descriptor); return; } #ifndef WATCHER_H #define WATCHER_H // standard #include #include enum FileStatus {modified, removed}; struct Event { std::string modified; std::string name; long long size; FileStatus status; }; std::list engage_watcher(const std::string &directory_path); void disengage_watcher(); #endif // WATCHER_H ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/mailman/listinfo/libev