Patch 7.4.1322
Problem: Crash when unletting the variable that holds the channel in a
callback function. (Christian Robinson)
Solution: Increase the reference count while invoking the callback.
Files: src/eval.c, src/channel.c, src/proto/eval.pro,
src/testdir/test_channel.vim
*** ../vim-7.4.1321/src/eval.c 2016-02-14 19:13:37.322808585 +0100
--- src/eval.c 2016-02-15 20:33:00.366026959 +0100
***************
*** 7730,7741 ****
return OK;
}
! #ifdef FEAT_CHANNEL
! static void
channel_unref(channel_T *channel)
{
if (channel != NULL && --channel->ch_refcount <= 0)
channel_free(channel);
}
#endif
--- 7730,7750 ----
return OK;
}
! #if defined(FEAT_CHANNEL) || defined(PROTO)
! /*
! * Decrement the reference count on "channel" and free it when it goes down to
! * zero.
! * Returns TRUE when the channel was freed.
! */
! int
channel_unref(channel_T *channel)
{
if (channel != NULL && --channel->ch_refcount <= 0)
+ {
channel_free(channel);
+ return TRUE;
+ }
+ return FALSE;
}
#endif
*** ../vim-7.4.1321/src/channel.c 2016-02-14 23:02:29.834701666 +0100
--- src/channel.c 2016-02-15 20:33:58.253422141 +0100
***************
*** 1217,1224 ****
#endif
channel->ch_close_cb = NULL;
- vim_free(channel->ch_callback);
- channel->ch_callback = NULL;
channel_clear(channel);
}
--- 1217,1222 ----
***************
*** 1298,1303 ****
--- 1296,1304 ----
free_tv(json_head->jq_next->jq_value);
remove_json_node(json_head, json_head->jq_next);
}
+
+ vim_free(channel->ch_callback);
+ channel->ch_callback = NULL;
}
#if defined(EXITFREE) || defined(PROTO)
***************
*** 1802,1816 ****
int
channel_parse_messages(void)
{
! channel_T *channel;
! int ret = FALSE;
! for (channel = first_channel; channel != NULL; channel = channel->ch_next)
! while (may_invoke_callback(channel) == OK)
{
! channel = first_channel; /* start over */
ret = TRUE;
}
return ret;
}
--- 1803,1830 ----
int
channel_parse_messages(void)
{
! channel_T *channel = first_channel;
! int ret = FALSE;
! int r;
!
! while (channel != NULL)
! {
! /* Increase the refcount, in case the handler causes the channel to be
! * unreferenced or closed. */
! ++channel->ch_refcount;
! r = may_invoke_callback(channel);
! if (channel_unref(channel))
! /* channel was freed, start over */
! channel = first_channel;
! if (r == OK)
{
! channel = first_channel; /* something was done, start over */
ret = TRUE;
}
+ else
+ channel = channel->ch_next;
+ }
return ret;
}
*** ../vim-7.4.1321/src/proto/eval.pro 2016-02-01 21:38:13.319011999 +0100
--- src/proto/eval.pro 2016-02-15 20:33:04.245986420 +0100
***************
*** 79,84 ****
--- 79,85 ----
dictitem_T *dict_find(dict_T *d, char_u *key, int len);
char_u *get_dict_string(dict_T *d, char_u *key, int save);
long get_dict_number(dict_T *d, char_u *key);
+ int channel_unref(channel_T *channel);
int string2float(char_u *text, float_T *value);
char_u *get_function_name(expand_T *xp, int idx);
char_u *get_expr_name(expand_T *xp, int idx);
*** ../vim-7.4.1321/src/testdir/test_channel.vim 2016-02-14
00:19:55.088992301 +0100
--- src/testdir/test_channel.vim 2016-02-15 20:38:56.042294334 +0100
***************
*** 295,297 ****
--- 295,315 ----
call job_stop(job)
endtry
endfunc
+
+ let s:unletResponse = ''
+ func s:UnletHandler(handle, msg)
+ let s:unletResponse = a:msg
+ unlet s:channelfd
+ endfunc
+
+ " Test that "unlet handle" in a handler doesn't crash Vim.
+ func s:unlet_handle(port)
+ let s:channelfd = ch_open('localhost:' . a:port, s:chopt)
+ call ch_sendexpr(s:channelfd, "test", function('s:UnletHandler'))
+ sleep 10m
+ call assert_equal('what?', s:unletResponse)
+ endfunc
+
+ func Test_unlet_handle()
+ call s:run_server('s:unlet_handle')
+ endfunc
*** ../vim-7.4.1321/src/version.c 2016-02-15 12:44:16.221956302 +0100
--- src/version.c 2016-02-15 20:37:05.635459200 +0100
***************
*** 749,750 ****
--- 749,752 ----
{ /* Add new patch number below this line */
+ /**/
+ 1322,
/**/
--
hundred-and-one symptoms of being an internet addict:
265. Your reason for not staying in touch with family is that
they do not have e-mail addresses.
/// 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.