[geany/geany-plugins] 84745f: git-changebar: Fix a race condition updating the diff
Colomban Wendling
git-noreply at xxxxx
Tue Jun 23 20:29:34 UTC 2015
Branch: refs/heads/master
Author: Colomban Wendling <ban at herbesfolles.org>
Committer: Colomban Wendling <ban at herbesfolles.org>
Date: Tue, 23 Jun 2015 20:29:34 UTC
Commit: 84745fe6046fcab626f7dd68e91b44f5f48c1090
https://github.com/geany/geany-plugins/commit/84745fe6046fcab626f7dd68e91b44f5f48c1090
Log Message:
-----------
git-changebar: Fix a race condition updating the diff
As the updates are delayed through an idle callback, but the cached
contents is cleared right when scheduling the idle callback, and the
thread also reports results through idle callbacks, it is possible for
a thread job to be reported between the moment the cached content is
cleared and the idle callback checks for the cache, leading to the use
of that job's result instead of scheduling a new one.
Fix this by tagging the cache with the document ID, allowing to check
not only if the cache is present but also whether it is actually valid
for the requested update.
Closes #244.
Modified Paths:
--------------
git-changebar/src/gcb-plugin.c
Modified: git-changebar/src/gcb-plugin.c
25 lines changed, 17 insertions(+), 8 deletions(-)
===================================================================
@@ -82,6 +82,7 @@ typedef void (*BlobContentsReadyFunc) (const gchar *path,
typedef struct AsyncBlobContentsJob AsyncBlobContentsJob;
struct AsyncBlobContentsJob {
gboolean force;
+ guint tag;
gchar *path;
git_buf buf;
BlobContentsReadyFunc callback;
@@ -140,6 +141,7 @@ static void write_setting_boolean (GKeyFile *kf,
/* cache */
static git_buf G_blob_contents = { 0 };
+static guint G_blob_contents_tag = 0;
/* global state */
static GAsyncQueue *G_queue = NULL;
static GThread *G_thread = NULL;
@@ -213,6 +215,7 @@ clear_cached_blob_contents (void)
git_buf_free (&G_blob_contents);
buf_zero (&G_blob_contents);
}
+ G_blob_contents_tag = 0;
}
/* get the file blob for @relpath at HEAD */
@@ -278,6 +281,7 @@ report_work_in_idle (gpointer data)
/* update cached blob */
clear_cached_blob_contents ();
G_blob_contents = job->buf;
+ G_blob_contents_tag = job->buf.ptr ? job->tag : 0;
job->callback (job->path, job->buf.ptr ? &job->buf : NULL, job->user_data);
@@ -455,16 +459,19 @@ worker_thread (gpointer data)
static void
get_cached_blob_contents_async (const gchar *path,
+ guint tag,
gboolean force,
BlobContentsReadyFunc callback,
gpointer user_data)
{
- if ((! force && G_blob_contents.ptr) || ! path) {
+ if ((! force && G_blob_contents.ptr && tag == G_blob_contents_tag) ||
+ ! path) {
callback (path, &G_blob_contents, user_data);
} else {
AsyncBlobContentsJob *job = g_slice_alloc (sizeof *job);
job->force = force;
+ job->tag = tag;
job->path = g_strdup (path);
job->callback = callback;
job->user_data = user_data;
@@ -801,7 +808,8 @@ on_sci_query_tooltip (GtkWidget *widget,
min_x = scintilla_send_message (sci, SCI_GETMARGINWIDTHN, 0, 0);
max_x = min_x + scintilla_send_message (sci, SCI_GETMARGINWIDTHN, 1, 0);
- if (x >= min_x && x <= max_x && G_blob_contents.ptr) {
+ if (x >= min_x && x <= max_x &&
+ G_blob_contents.ptr && G_blob_contents_tag == doc->id) {
gint pos = scintilla_send_message (sci, SCI_POSITIONFROMPOINT, x, y);
gint line = sci_get_line_from_position (sci, pos);
gint mask = scintilla_send_message (sci, SCI_MARKERGET, line, 0);
@@ -861,7 +869,7 @@ do_update_diff_idle (guint doc_id,
G_source_id = 0;
/* make sure the document is still valid and current */
if (doc && doc->id == doc_id) {
- get_cached_blob_contents_async (doc->real_path, force, update_diff,
+ get_cached_blob_contents_async (doc->real_path, doc_id, force, update_diff,
GUINT_TO_POINTER (doc->id));
}
@@ -1024,8 +1032,8 @@ on_kb_goto_next_hunk (guint kb)
data->line = sci_get_current_line (doc->editor->sci);
data->next_line = -1;
- get_cached_blob_contents_async (doc->real_path, FALSE, goto_next_hunk_cb,
- data);
+ get_cached_blob_contents_async (doc->real_path, doc->id, FALSE,
+ goto_next_hunk_cb, data);
}
}
@@ -1197,9 +1205,10 @@ plugin_init (GeanyData *data)
GeanyKeyGroup *kb_group;
buf_zero (&G_blob_contents);
- G_source_id = 0;
- G_thread = NULL;
- G_queue = NULL;
+ G_blob_contents_tag = 0;
+ G_source_id = 0;
+ G_thread = NULL;
+ G_queue = NULL;
if (git_libgit2_init () < 0) {
const git_error *err = giterr_last ();
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Plugins-Commits
mailing list