Mercurial > vim
comparison src/channel.c @ 8055:6db4b1c863ec v7.4.1322
commit https://github.com/vim/vim/commit/3bece9fee9c02934d3e295b29d253e13d4ef26a7
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Feb 15 20:39:46 2016 +0100
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.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Mon, 15 Feb 2016 20:45:04 +0100 |
parents | 15253130abd8 |
children | 19304db153bc |
comparison
equal
deleted
inserted
replaced
8054:adb3150edaaf | 8055:6db4b1c863ec |
---|---|
1215 channel->CH_ERR = -1; | 1215 channel->CH_ERR = -1; |
1216 } | 1216 } |
1217 #endif | 1217 #endif |
1218 | 1218 |
1219 channel->ch_close_cb = NULL; | 1219 channel->ch_close_cb = NULL; |
1220 vim_free(channel->ch_callback); | |
1221 channel->ch_callback = NULL; | |
1222 channel_clear(channel); | 1220 channel_clear(channel); |
1223 } | 1221 } |
1224 | 1222 |
1225 /* | 1223 /* |
1226 * Store "buf[len]" on channel "channel". | 1224 * Store "buf[len]" on channel "channel". |
1296 while (json_head->jq_next != NULL) | 1294 while (json_head->jq_next != NULL) |
1297 { | 1295 { |
1298 free_tv(json_head->jq_next->jq_value); | 1296 free_tv(json_head->jq_next->jq_value); |
1299 remove_json_node(json_head, json_head->jq_next); | 1297 remove_json_node(json_head, json_head->jq_next); |
1300 } | 1298 } |
1299 | |
1300 vim_free(channel->ch_callback); | |
1301 channel->ch_callback = NULL; | |
1301 } | 1302 } |
1302 | 1303 |
1303 #if defined(EXITFREE) || defined(PROTO) | 1304 #if defined(EXITFREE) || defined(PROTO) |
1304 void | 1305 void |
1305 channel_free_all(void) | 1306 channel_free_all(void) |
1800 * Return TRUE when something was done. | 1801 * Return TRUE when something was done. |
1801 */ | 1802 */ |
1802 int | 1803 int |
1803 channel_parse_messages(void) | 1804 channel_parse_messages(void) |
1804 { | 1805 { |
1805 channel_T *channel; | 1806 channel_T *channel = first_channel; |
1806 int ret = FALSE; | 1807 int ret = FALSE; |
1807 | 1808 int r; |
1808 for (channel = first_channel; channel != NULL; channel = channel->ch_next) | 1809 |
1809 while (may_invoke_callback(channel) == OK) | 1810 while (channel != NULL) |
1810 { | 1811 { |
1811 channel = first_channel; /* start over */ | 1812 /* Increase the refcount, in case the handler causes the channel to be |
1813 * unreferenced or closed. */ | |
1814 ++channel->ch_refcount; | |
1815 r = may_invoke_callback(channel); | |
1816 if (channel_unref(channel)) | |
1817 /* channel was freed, start over */ | |
1818 channel = first_channel; | |
1819 | |
1820 if (r == OK) | |
1821 { | |
1822 channel = first_channel; /* something was done, start over */ | |
1812 ret = TRUE; | 1823 ret = TRUE; |
1813 } | 1824 } |
1825 else | |
1826 channel = channel->ch_next; | |
1827 } | |
1814 return ret; | 1828 return ret; |
1815 } | 1829 } |
1816 | 1830 |
1817 /* | 1831 /* |
1818 * Mark references to lists used in channels. | 1832 * Mark references to lists used in channels. |