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, &err);
    ...

    /* 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.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]