#endif
channel->ch_close_cb = NULL;
- vim_free(channel->ch_callback);
- channel->ch_callback = NULL;
channel_clear(channel);
}
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)
int
channel_parse_messages(void)
{
- channel_T *channel;
- int ret = FALSE;
+ channel_T *channel = first_channel;
+ int ret = FALSE;
+ int r;
- for (channel = first_channel; channel != NULL; channel = channel->ch_next)
- while (may_invoke_callback(channel) == OK)
+ 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; /* start over */
+ channel = first_channel; /* something was done, start over */
ret = TRUE;
}
+ else
+ channel = channel->ch_next;
+ }
return ret;
}
return OK;
}
-#ifdef FEAT_CHANNEL
- static void
+#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
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);
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
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1322,
/**/
1321,
/**/