Patch 7.4.2026
Problem:    Reference counting for callbacks isn't right.
Solution:   Add free_callback(). (Ken Takata)  Fix reference count.
Files:      src/channel.c, src/eval.c, src/ex_cmds2.c, src/proto/eval.pro


*** ../vim-7.4.2025/src/channel.c       2016-07-10 22:11:11.858751521 +0200
--- src/channel.c       2016-07-11 22:36:04.665368667 +0200
***************
*** 1113,1118 ****
--- 1113,1135 ----
      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,1127 ****
  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)
--- 1137,1142 ----
***************
*** 1144,1204 ****
        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;
!     }
      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;
!     }
      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;
!     }
      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;
!     }
  
      if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER)
      {
--- 1159,1177 ----
        channel->ch_part[PART_IN].ch_block_write = 1;
  
      if (opt->jo_set & JO_CALLBACK)
!       set_callback(&channel->ch_callback, &channel->ch_partial,
!                                          opt->jo_callback, opt->jo_partial);
      if (opt->jo_set & JO_OUT_CALLBACK)
!       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)
!       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)
!       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,2235 ****
       * 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);
      vim_free(item);
  }
  
--- 2201,2207 ----
       * invokes ch_close() the list will be cleared. */
      remove_cb_node(cbhead, item);
      invoke_callback(channel, item->cq_callback, item->cq_partial, argv);
!     free_callback(item->cq_callback, item->cq_partial);
      vim_free(item);
  }
  
***************
*** 2725,2733 ****
          }
  
          /* the callback is only called once */
!         vim_free(channel->ch_close_cb);
          channel->ch_close_cb = NULL;
-         partial_unref(channel->ch_close_partial);
          channel->ch_close_partial = NULL;
  
          --channel->ch_refcount;
--- 2697,2704 ----
          }
  
          /* the callback is only called once */
!         free_callback(channel->ch_close_cb, channel->ch_close_partial);
          channel->ch_close_cb = NULL;
          channel->ch_close_partial = NULL;
  
          --channel->ch_refcount;
***************
*** 2763,2770 ****
        cbq_T *node = cb_head->cq_next;
  
        remove_cb_node(cb_head, node);
!       vim_free(node->cq_callback);
!       partial_unref(node->cq_partial);
        vim_free(node);
      }
  
--- 2734,2740 ----
        cbq_T *node = cb_head->cq_next;
  
        remove_cb_node(cb_head, node);
!       free_callback(node->cq_callback, node->cq_partial);
        vim_free(node);
      }
  
***************
*** 2774,2782 ****
        remove_json_node(json_head, json_head->jq_next);
      }
  
!     vim_free(channel->ch_part[part].ch_callback);
      channel->ch_part[part].ch_callback = NULL;
-     partial_unref(channel->ch_part[part].ch_partial);
      channel->ch_part[part].ch_partial = NULL;
  }
  
--- 2744,2752 ----
        remove_json_node(json_head, json_head->jq_next);
      }
  
!     free_callback(channel->ch_part[part].ch_callback,
!                                       channel->ch_part[part].ch_partial);
      channel->ch_part[part].ch_callback = NULL;
      channel->ch_part[part].ch_partial = NULL;
  }
  
***************
*** 2793,2805 ****
      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);
      channel->ch_callback = NULL;
-     partial_unref(channel->ch_partial);
      channel->ch_partial = NULL;
!     vim_free(channel->ch_close_cb);
      channel->ch_close_cb = NULL;
-     partial_unref(channel->ch_close_partial);
      channel->ch_close_partial = NULL;
  }
  
--- 2763,2773 ----
      channel_clear_one(channel, PART_OUT);
      channel_clear_one(channel, PART_ERR);
      /* there is no callback or queue for PART_IN */
!     free_callback(channel->ch_callback, channel->ch_partial);
      channel->ch_callback = NULL;
      channel->ch_partial = NULL;
!     free_callback(channel->ch_close_cb, channel->ch_close_partial);
      channel->ch_close_cb = NULL;
      channel->ch_close_partial = NULL;
  }
  
***************
*** 4319,4326 ****
      mch_clear_job(job);
  
      vim_free(job->jv_stoponexit);
!     vim_free(job->jv_exit_cb);
!     partial_unref(job->jv_exit_partial);
  }
  
      static void
--- 4287,4293 ----
      mch_clear_job(job);
  
      vim_free(job->jv_stoponexit);
!     free_callback(job->jv_exit_cb, job->jv_exit_partial);
  }
  
      static void
***************
*** 4485,4492 ****
      }
      if (opt->jo_set & JO_EXIT_CB)
      {
!       vim_free(job->jv_exit_cb);
!       partial_unref(job->jv_exit_partial);
        if (opt->jo_exit_cb == NULL || *opt->jo_exit_cb == NUL)
        {
            job->jv_exit_cb = NULL;
--- 4452,4458 ----
      }
      if (opt->jo_set & JO_EXIT_CB)
      {
!       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;
*** ../vim-7.4.2025/src/eval.c  2016-07-10 22:11:11.862751461 +0200
--- src/eval.c  2016-07-11 22:36:52.976641709 +0200
***************
*** 21178,21190 ****
        return (*pp)->pt_name;
      }
      *pp = NULL;
!     if (arg->v_type == VAR_FUNC || 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;
  }
  #endif
  
  #ifdef FEAT_TIMERS
--- 21178,21210 ----
        return (*pp)->pt_name;
      }
      *pp = NULL;
!     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
*** ../vim-7.4.2025/src/ex_cmds2.c      2016-07-10 22:11:11.862751461 +0200
--- src/ex_cmds2.c      2016-07-11 21:19:24.494478162 +0200
***************
*** 1121,1128 ****
      static void
  free_timer(timer_T *timer)
  {
!     vim_free(timer->tr_callback);
!     partial_unref(timer->tr_partial);
      vim_free(timer);
  }
  
--- 1121,1127 ----
      static void
  free_timer(timer_T *timer)
  {
!     free_callback(timer->tr_callback, timer->tr_partial);
      vim_free(timer);
  }
  
*** ../vim-7.4.2025/src/proto/eval.pro  2016-07-09 17:05:49.207222368 +0200
--- src/proto/eval.pro  2016-07-11 21:14:40.566748633 +0200
***************
*** 94,99 ****
--- 94,100 ----
  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);
*** ../vim-7.4.2025/src/version.c       2016-07-10 23:16:05.112753072 +0200
--- src/version.c       2016-07-11 21:16:41.752925492 +0200
***************
*** 760,761 ****
--- 760,763 ----
  {   /* Add new patch number below this line */
+ /**/
+     2026,
  /**/

-- 
       We're knights of the round table
       We dance whene'er we're able
       We do routines and chorus scenes
       With footwork impeccable.
       We dine well here in Camelot
       We eat ham and jam and spam a lot.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui