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.