]> granicus.if.org Git - vim/commitdiff
patch 7.4.2026 v7.4.2026
authorBram Moolenaar <Bram@vim.org>
Mon, 11 Jul 2016 20:41:15 +0000 (22:41 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 11 Jul 2016 20:41:15 +0000 (22:41 +0200)
Problem:    Reference counting for callbacks isn't right.
Solution:   Add free_callback(). (Ken Takata)  Fix reference count.

src/channel.c
src/eval.c
src/ex_cmds2.c
src/proto/eval.pro
src/version.c

index 2e880804146d65c296c1ec8a27990e89f6fff691..90ef9741af06dbbde7ba4bafaf6210ec10385ea9 100644 (file)
@@ -1113,6 +1113,23 @@ find_buffer(char_u *name, int err)
     return buf;
 }
 
+    static void
+set_callback(
+       char_u **cbp,
+       partial_T **pp,
+       char_u *callback,
+       partial_T *partial)
+{
+    free_callback(*cbp, *pp);
+    if (callback != NULL && *callback != NUL)
+       *cbp = vim_strsave(callback);
+    else
+       *cbp = NULL;
+    *pp = partial;
+    if (*pp != NULL)
+       ++(*pp)->pt_refcount;
+}
+
 /*
  * Set various properties from an "opt" argument.
  */
@@ -1120,8 +1137,6 @@ find_buffer(char_u *name, int err)
 channel_set_options(channel_T *channel, jobopt_T *opt)
 {
     int                part;
-    char_u     **cbp;
-    partial_T  **pp;
 
     if (opt->jo_set & JO_MODE)
        for (part = PART_SOCK; part <= PART_IN; ++part)
@@ -1144,61 +1159,19 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
        channel->ch_part[PART_IN].ch_block_write = 1;
 
     if (opt->jo_set & JO_CALLBACK)
-    {
-       cbp = &channel->ch_callback;
-       pp = &channel->ch_partial;
-       vim_free(*cbp);
-       partial_unref(*pp);
-       if (opt->jo_callback != NULL && *opt->jo_callback != NUL)
-           *cbp = vim_strsave(opt->jo_callback);
-       else
-           *cbp = NULL;
-       *pp = opt->jo_partial;
-       if (*pp != NULL)
-           ++(*pp)->pt_refcount;
-    }
+       set_callback(&channel->ch_callback, &channel->ch_partial,
+                                          opt->jo_callback, opt->jo_partial);
     if (opt->jo_set & JO_OUT_CALLBACK)
-    {
-       cbp = &channel->ch_part[PART_OUT].ch_callback;
-       pp = &channel->ch_part[PART_OUT].ch_partial;
-       vim_free(*cbp);
-       partial_unref(*pp);
-       if (opt->jo_out_cb != NULL && *opt->jo_out_cb != NUL)
-           *cbp = vim_strsave(opt->jo_out_cb);
-       else
-           *cbp = NULL;
-       *pp = opt->jo_out_partial;
-       if (*pp != NULL)
-           ++(*pp)->pt_refcount;
-    }
+       set_callback(&channel->ch_part[PART_OUT].ch_callback,
+               &channel->ch_part[PART_OUT].ch_partial,
+               opt->jo_out_cb, opt->jo_out_partial);
     if (opt->jo_set & JO_ERR_CALLBACK)
-    {
-       cbp = &channel->ch_part[PART_ERR].ch_callback;
-       pp = &channel->ch_part[PART_ERR].ch_partial;
-       vim_free(*cbp);
-       partial_unref(*pp);
-       if (opt->jo_err_cb != NULL && *opt->jo_err_cb != NUL)
-           *cbp = vim_strsave(opt->jo_err_cb);
-       else
-           *cbp = NULL;
-       *pp = opt->jo_err_partial;
-       if (*pp != NULL)
-           ++(*pp)->pt_refcount;
-    }
+       set_callback(&channel->ch_part[PART_ERR].ch_callback,
+               &channel->ch_part[PART_ERR].ch_partial,
+               opt->jo_err_cb, opt->jo_err_partial);
     if (opt->jo_set & JO_CLOSE_CALLBACK)
-    {
-       cbp = &channel->ch_close_cb;
-       pp = &channel->ch_close_partial;
-       vim_free(*cbp);
-       partial_unref(*pp);
-       if (opt->jo_close_cb != NULL && *opt->jo_close_cb != NUL)
-           *cbp = vim_strsave(opt->jo_close_cb);
-       else
-           *cbp = NULL;
-       *pp = opt->jo_close_partial;
-       if (*pp != NULL)
-           ++(*pp)->pt_refcount;
-    }
+       set_callback(&channel->ch_close_cb, &channel->ch_close_partial,
+               opt->jo_close_cb, opt->jo_close_partial);
 
     if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER)
     {
@@ -2228,8 +2201,7 @@ invoke_one_time_callback(
      * invokes ch_close() the list will be cleared. */
     remove_cb_node(cbhead, item);
     invoke_callback(channel, item->cq_callback, item->cq_partial, argv);
-    vim_free(item->cq_callback);
-    partial_unref(item->cq_partial);
+    free_callback(item->cq_callback, item->cq_partial);
     vim_free(item);
 }
 
@@ -2725,9 +2697,8 @@ channel_close(channel_T *channel, int invoke_close_cb)
          }
 
          /* the callback is only called once */
-         vim_free(channel->ch_close_cb);
+         free_callback(channel->ch_close_cb, channel->ch_close_partial);
          channel->ch_close_cb = NULL;
-         partial_unref(channel->ch_close_partial);
          channel->ch_close_partial = NULL;
 
          --channel->ch_refcount;
@@ -2763,8 +2734,7 @@ channel_clear_one(channel_T *channel, int part)
        cbq_T *node = cb_head->cq_next;
 
        remove_cb_node(cb_head, node);
-       vim_free(node->cq_callback);
-       partial_unref(node->cq_partial);
+       free_callback(node->cq_callback, node->cq_partial);
        vim_free(node);
     }
 
@@ -2774,9 +2744,9 @@ channel_clear_one(channel_T *channel, int part)
        remove_json_node(json_head, json_head->jq_next);
     }
 
-    vim_free(channel->ch_part[part].ch_callback);
+    free_callback(channel->ch_part[part].ch_callback,
+                                       channel->ch_part[part].ch_partial);
     channel->ch_part[part].ch_callback = NULL;
-    partial_unref(channel->ch_part[part].ch_partial);
     channel->ch_part[part].ch_partial = NULL;
 }
 
@@ -2793,13 +2763,11 @@ channel_clear(channel_T *channel)
     channel_clear_one(channel, PART_OUT);
     channel_clear_one(channel, PART_ERR);
     /* there is no callback or queue for PART_IN */
-    vim_free(channel->ch_callback);
+    free_callback(channel->ch_callback, channel->ch_partial);
     channel->ch_callback = NULL;
-    partial_unref(channel->ch_partial);
     channel->ch_partial = NULL;
-    vim_free(channel->ch_close_cb);
+    free_callback(channel->ch_close_cb, channel->ch_close_partial);
     channel->ch_close_cb = NULL;
-    partial_unref(channel->ch_close_partial);
     channel->ch_close_partial = NULL;
 }
 
@@ -4319,8 +4287,7 @@ job_free_contents(job_T *job)
     mch_clear_job(job);
 
     vim_free(job->jv_stoponexit);
-    vim_free(job->jv_exit_cb);
-    partial_unref(job->jv_exit_partial);
+    free_callback(job->jv_exit_cb, job->jv_exit_partial);
 }
 
     static void
@@ -4485,8 +4452,7 @@ job_set_options(job_T *job, jobopt_T *opt)
     }
     if (opt->jo_set & JO_EXIT_CB)
     {
-       vim_free(job->jv_exit_cb);
-       partial_unref(job->jv_exit_partial);
+       free_callback(job->jv_exit_cb, job->jv_exit_partial);
        if (opt->jo_exit_cb == NULL || *opt->jo_exit_cb == NUL)
        {
            job->jv_exit_cb = NULL;
index a9504363d197588f67abb099885b6c51949c6c49..779886431ea1eb4c8fff11aba0d3364f109bba52 100644 (file)
@@ -21178,13 +21178,33 @@ get_callback(typval_T *arg, partial_T **pp)
        return (*pp)->pt_name;
     }
     *pp = NULL;
-    if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
+    if (arg->v_type == VAR_FUNC)
+    {
+       func_ref(arg->vval.v_string);
+       return arg->vval.v_string;
+    }
+    if (arg->v_type == VAR_STRING)
        return arg->vval.v_string;
     if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
        return (char_u *)"";
     EMSG(_("E921: Invalid callback argument"));
     return NULL;
 }
+
+/*
+ * Unref/free "callback" and "partial" retured by get_callback().
+ */
+    void
+free_callback(char_u *callback, partial_T *partial)
+{
+    if (partial != NULL)
+       partial_unref(partial);
+    else if (callback != NULL)
+    {
+       func_unref(callback);
+       vim_free(callback);
+    }
+}
 #endif
 
 #ifdef FEAT_TIMERS
index c8980b44b70e6d5019276a441df538bc40da93b6..2b2d63549f3cf06d3088faf4997d3d4ba50f7a5f 100644 (file)
@@ -1121,8 +1121,7 @@ remove_timer(timer_T *timer)
     static void
 free_timer(timer_T *timer)
 {
-    vim_free(timer->tr_callback);
-    partial_unref(timer->tr_partial);
+    free_callback(timer->tr_callback, timer->tr_partial);
     vim_free(timer);
 }
 
index e81669b05eb62d0286eb3a7be07461736cd91927..6d1144776b3a5bd9bdd8509371caaf48f8674021 100644 (file)
@@ -94,6 +94,7 @@ void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
 float_T vim_round(float_T f);
 long do_searchpair(char_u *spat, char_u *mpat, char_u *epat, int dir, char_u *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, long time_limit);
 char_u *get_callback(typval_T *arg, partial_T **pp);
+void free_callback(char_u *callback, partial_T *partial);
 void set_vim_var_nr(int idx, varnumber_T val);
 varnumber_T get_vim_var_nr(int idx);
 char_u *get_vim_var_str(int idx);
index 67f8b653e17f4127df8d357c305bb7e7c5d9177b..a7a9a8bd90f11eafa39345a38db717639e15e0c9 100644 (file)
@@ -758,6 +758,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2026,
 /**/
     2025,
 /**/