Re: GFileMonitor - g_signal_handler_block "changed" signal doesn't block handler?
On 04/01/2017 01:04 PM, cecas...@aol.com wrote: > > Hi David, > > Not sure about this one. I tested some code out to see if I could figure it > out. Had the same problem that you had with the "changed" signal not being > blocked. If I change the rate of the file monitor and try to spool out the > events, I can block the "changed" signal. Not something that I would recommend > doing outside of testing so I suspect there is a better way to go about it. > Blocking the "changed" signal isn't going to solve the problem of knowing > where the change is coming from which can come from another process at any > time. Maybe if you had a pid in the "changed" callback, then you could compare > it with your program pid to see if the change is coming from your program or > someplace else. > > The following is what I tried using gedit and the terminal. Hopefully you get > some better ideas. > > Eric > Thank you Eric, I will tinker with what you have tried and see if I can figure out more how GFileMonitor signal handling is different from default GTK. I've gotten some suggestions on StackOverflow, but more simply confirm your and my findings. Since GIO handling of the emission and blocking of "changed" is a big black box without picking though the source code, there are suggestions to just save the file 'stat' information and compare against any changed signal for foreign modification and setting a 'save' flag to ignore the "changed" signal during normal file saves. It's frustrating that the GFileMonitor "changed" signal handler block doesn't follow the normal block/unblock convention based on 'instance' and 'handler_id' alone. That certainly would provide a much more elegant solution. Worse case, I can always resort to the original 'inotify' implementation as the custom signal works fine with block/unblock. I'll just have to play with invoking the read from pselect with a g_idle_add of the callback that does that. I haven't played with that yet (as I've been chasing my tail on the GFileMonitor issue in spare time). -- David C. Rankin, J.D.,P.E. ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: GFileMonitor - g_signal_handler_block "changed" signal doesn't block handler?
Hi David, Not sure about this one. I tested some code out to see if I could figure it out. Had the same problem that you had with the "changed" signal not being blocked. If I change the rate of the file monitor and try to spool out the events, I can block the "changed" signal. Not something that I would recommend doing outside of testing so I suspect there is a better way to go about it. Blocking the "changed" signal isn't going to solve the problem of knowing where the change is coming from which can come from another process at any time. Maybe if you had a pid in the "changed" callback, then you could compare it with your program pid to see if the change is coming from your program or someplace else. The following is what I tried using gedit and the terminal. Hopefully you get some better ideas. Eric /* gcc -Wall file_monitor1.c -o file_monitor1 `pkg-config --cflags --libs gtk+-3.0` Tested on Ubuntu16.04, GTK3.18 and gedit. */ #include guint signal_id=0; GFileMonitor *filemon=NULL; //The file to append to. Just the .c file that is in the same folder as the program. gchar *path="file_monitor1.c"; //Check file changes from gedit and the file_monitor1 program. static void file_changed(GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data) { g_print("File Changed\n"); } static void button_clicked(GtkWidget *button, GFile *gfile) { g_print("Block\n"); g_signal_handler_block(filemon, signal_id); GError *err=NULL; GFileOutputStream *stream=g_file_append_to(gfile, G_FILE_CREATE_NONE, NULL, ); if(err!=NULL) g_print("%s\n", err->message); g_output_stream_write((GOutputStream*)stream, "//\n", 3, NULL, ); if(err!=NULL) g_print("%s\n", err->message); g_output_stream_close((GOutputStream*)stream, NULL, ); if(err!=NULL) g_print("%s\n", err->message); g_object_unref(stream); /* Give GIO some time to post the event. This is a test. Don't do this otherwise. From gfilemonitor.c #define DEFAULT_RATE_LIMIT_MSECS 800 for filemon. */ g_file_monitor_set_rate_limit(filemon, 100); g_usleep(1); while(gtk_events_pending()) gtk_main_iteration(); g_file_monitor_set_rate_limit(filemon, 800); g_signal_handler_unblock(filemon, signal_id); g_print("Unblock\n"); if(err!=NULL) g_error_free(err); } int main(int argc, char *argv[]) { gtk_init(, ); GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "File Monitor"); gtk_window_set_default_size(GTK_WINDOW(window), 200, 100); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_container_set_border_width(GTK_CONTAINER(window), 20); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); GFile *gfile=g_file_new_for_path(path); filemon=g_file_monitor_file(gfile, G_FILE_MONITOR_NONE, NULL, NULL); signal_id=g_signal_connect(filemon, "changed", G_CALLBACK(file_changed), NULL); GtkWidget *button=gtk_button_new_with_label("Append to file_monitor1.c"); gtk_widget_set_hexpand(button, TRUE); gtk_widget_set_vexpand(button, TRUE); g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), gfile); GtkWidget *grid=gtk_grid_new(); gtk_grid_attach(GTK_GRID(grid), button, 0, 0, 1, 1); gtk_container_add(GTK_CONTAINER(window), grid); gtk_widget_show_all(window); gtk_main(); g_object_unref(gfile); g_object_unref(filemon); return 0; } ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: GFileMonitor - g_signal_handler_block "changed" signal doesn't block handler?
On 03/30/2017 03:39 PM, David C. Rankin wrote: > Let me know what the experts think. There is something funny about the way > block/unblock works with GFileMonitor that I'm missing. For normal signals in > the app, I have no problems with block/unblock. I've posted this complete question to: http://stackoverflow.com/questions/43132025/gfilemonitor-g-signal-handler-block-changed-signal-doesnt-block-handler?noredirect=1#comment73342904_43132025 and I've uploaded the complete source to: https://github.com/drankinatty/gtktest if anyone needs additional detail about the issue. -- David C. Rankin, J.D.,P.E. ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
GFileMonitor - g_signal_handler_block "changed" signal doesn't block handler?
All I have implemented a GFileMonitor/g_file_monitor_file watch for respond to changes to the current file by an external process within an editor[1], but now issuing g_signal_handler_block to prevent the "changed" signal from being handled on normal saves, does not prevent the callback from firing. The basic flow is this, I set the watch with: GFile *gfile = g_file_new_for_path (app->filename); ... /* create monitor for app->filename */ app->filemon = g_file_monitor_file (gfile, G_FILE_MONITOR_NONE, cancellable, ); ... /* connect changed signal to monitored file saving ID */ app->mfp_handler = g_signal_connect (G_OBJECT(app->filemon), "changed", G_CALLBACK (file_monitor_on_changed), data); Both the instance (app->filemon) and handler_id (app->mfp_handler) are saved. In order to prevent handling of changes during normal save/save as operations, I created block and unblock functions to prevent the changes to the file from firing the callback, e.g. show below with debug g_print calls: void file_monitor_block_changed (gpointer data) { kwinst *app = (kwinst *)data; if (!app->filemon || !app->mfp_handler) return; g_print ("blocking changed (%lu)\n", app->mfp_handler); g_signal_handler_block (app->filemon, app->mfp_handler); } void file_monitor_unblock_changed (gpointer data) { kwinst *app = (kwinst *)data; if (!app->filemon || !app->mfp_handler) return; g_print ("unblocking changed (%lu)\n", app->mfp_handler); g_signal_handler_unblock (app->filemon, app->mfp_handler); } To implement the block/unblock, I wrap the file 'save/save as' function in the block, then save, then unblock, but the callback is still firing on normal saves. e.g. in the save function I have: if (app->mfp_handler) /* current file monitor on file */ file_monitor_block_changed (app); /* block "changed" signal */ g_print (" buffer_write_file (app, filename)\n"); buffer_write_file (app, filename); /* write to file app->filename */ if (filename) file_monitor_add (app); /* setup monitoring on new name */ else if (app->mfp_handler) file_monitor_unblock_changed (app); /* unblock "changed" signal */ To my disbelief, the callback continues to fire as if I had not called block at all. For instance when saving the file, the debug output is: $ ./bin/gtkwrite blocking changed (669) buffer_write_file (app, filename) unblocking changed (669) Monitor Event: File = /home/david/tmp/foo.txt.UY9IXY G_FILE_MONITOR_EVENT_DELETED Monitor Event: File = /home/david/tmp/foo.txt G_FILE_MONITOR_EVENT_CREATED Monitor Event: File = /home/david/tmp/foo.txt G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT Monitor Event: File = /home/david/tmp/foo.txt G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED from which I can see the block called, the call to save the file to disk, the unblock call, and then the callback firing to delete the temp file 'foo.txt.UY9IXY', and create the new 'foo.txt' and then setting the attributes. Why is this occurring? I get the exact same firing of the callback if I completely remove the block/unblock calls, so it is not due to gio using a temp file with the g_file_set_contents call during save. When I created my custom signal for using inotify directly, I could block/unblock that signal without any problem, but when using GFileMonitor, the block/unblock seems like it is completely ignored. All types are correct, e.g. from the basic struct app: GFileMonitor*filemon; gulong mfp_handler; So what is the trick? How to I prevent the file_monitor_on_changed() callback from firing in response to the "changed" signal on normal file saves. I shouldn't have to completely disconnect/reconnect the callback should I? The block/unblock should be sufficient for temporary use, right? Let me know what the experts think. There is something funny about the way block/unblock works with GFileMonitor that I'm missing. For normal signals in the app, I have no problems with block/unblock. Footnote [1]: (see earlier post "Howto integrate an inotify watch on editor file in GTK+2 event loop?") -- David C. Rankin, J.D.,P.E. ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list