diff src/channel.c @ 9491:404de131cff9 v7.4.2026

commit https://github.com/vim/vim/commit/1436d8d51cce114be56209924fc71376407e5bad Author: Bram Moolenaar <Bram@vim.org> Date: Mon Jul 11 22:41:15 2016 +0200 patch 7.4.2026 Problem: Reference counting for callbacks isn't right. Solution: Add free_callback(). (Ken Takata) Fix reference count.
author Christian Brabandt <cb@256bit.org>
date Mon, 11 Jul 2016 22:45:05 +0200
parents 69ed2c9d34a6
children 581d5131629f
line wrap: on
line diff
--- a/src/channel.c
+++ b/src/channel.c
@@ -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, 
 	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 in
 	  }
 
 	  /* 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, in
 	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, in
 	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 *op
     }
     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;