Mercurial > vim
comparison src/channel.c @ 8257:c4ffdda8cdfd v7.4.1421
commit https://github.com/vim/vim/commit/c8dcbb12c5d7f3eb0c334daebb4475bb015b91e7
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Feb 25 23:10:17 2016 +0100
patch 7.4.1421
Problem: May free a channel when a callback may need to be invoked.
Solution: Keep the channel when refcount is zero.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 25 Feb 2016 23:15:05 +0100 |
parents | 60586ce747c4 |
children | 99a70c3b902f |
comparison
equal
deleted
inserted
replaced
8256:1a895d499690 | 8257:c4ffdda8cdfd |
---|---|
302 } | 302 } |
303 first_channel = channel; | 303 first_channel = channel; |
304 | 304 |
305 channel->ch_refcount = 1; | 305 channel->ch_refcount = 1; |
306 return channel; | 306 return channel; |
307 } | |
308 | |
309 /* | |
310 * Return TRUE if "channel" has a callback. | |
311 */ | |
312 static int | |
313 channel_has_callback(channel_T *channel) | |
314 { | |
315 return channel->ch_callback != NULL | |
316 #ifdef CHANNEL_PIPES | |
317 || channel->ch_part[PART_OUT].ch_callback != NULL | |
318 || channel->ch_part[PART_ERR].ch_callback != NULL | |
319 #endif | |
320 || channel->ch_close_cb != NULL; | |
321 } | |
322 | |
323 /* | |
324 * Close a channel and free all its resources if there is no further action | |
325 * possible, there is no callback to be invoked. | |
326 */ | |
327 void | |
328 channel_may_free(channel_T *channel) | |
329 { | |
330 if (!channel_has_callback(channel)) | |
331 channel_free(channel); | |
307 } | 332 } |
308 | 333 |
309 /* | 334 /* |
310 * Close a channel and free all its resources. | 335 * Close a channel and free all its resources. |
311 */ | 336 */ |
1461 return "closed"; | 1486 return "closed"; |
1462 } | 1487 } |
1463 | 1488 |
1464 /* | 1489 /* |
1465 * Close channel "channel". | 1490 * Close channel "channel". |
1466 * This does not trigger the close callback. | 1491 * Trigger the close callback if "invoke_close_cb" is TRUE. |
1467 */ | 1492 */ |
1468 void | 1493 void |
1469 channel_close(channel_T *channel, int invoke_close_cb) | 1494 channel_close(channel_T *channel, int invoke_close_cb) |
1470 { | 1495 { |
1471 ch_log(channel, "Closing channel"); | 1496 ch_log(channel, "Closing channel"); |
2147 int r; | 2172 int r; |
2148 int part = PART_SOCK; | 2173 int part = PART_SOCK; |
2149 | 2174 |
2150 while (channel != NULL) | 2175 while (channel != NULL) |
2151 { | 2176 { |
2177 if (channel->ch_refcount == 0 && !channel_has_callback(channel)) | |
2178 { | |
2179 /* channel is no longer useful, free it */ | |
2180 channel_free(channel); | |
2181 channel = first_channel; | |
2182 part = PART_SOCK; | |
2183 continue; | |
2184 } | |
2152 if (channel->ch_part[part].ch_fd != INVALID_FD) | 2185 if (channel->ch_part[part].ch_fd != INVALID_FD) |
2153 { | 2186 { |
2154 /* Increase the refcount, in case the handler causes the channel | 2187 /* Increase the refcount, in case the handler causes the channel |
2155 * to be unreferenced or closed. */ | 2188 * to be unreferenced or closed. */ |
2156 ++channel->ch_refcount; | 2189 ++channel->ch_refcount; |