Mercurial > vim
comparison src/channel.c @ 9083:69bb7b230094 v7.4.1826
commit https://github.com/vim/vim/commit/cf7ff70ca73218d618e7c00ab785bcf5f9120a94
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon May 9 17:20:14 2016 +0200
patch 7.4.1826
Problem: Callbacks are invoked when it's not safe. (Andrew Stewart)
Solution: When a channel is to be closed don't invoke callbacks right away,
wait for a safe moment.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Mon, 09 May 2016 17:30:06 +0200 |
parents | b2b915c1d311 |
children | d362e6df1deb |
comparison
equal
deleted
inserted
replaced
9082:ed95e35d74bd | 9083:69bb7b230094 |
---|---|
2780 | 2780 |
2781 static void | 2781 static void |
2782 channel_close_on_error(channel_T *channel, char *func) | 2782 channel_close_on_error(channel_T *channel, char *func) |
2783 { | 2783 { |
2784 /* Do not call emsg(), most likely the other end just exited. */ | 2784 /* Do not call emsg(), most likely the other end just exited. */ |
2785 ch_errors(channel, "%s(): Cannot read from channel", func); | 2785 ch_errors(channel, "%s(): Cannot read from channel, will close it soon", |
2786 func); | |
2786 | 2787 |
2787 /* Queue a "DETACH" netbeans message in the command queue in order to | 2788 /* Queue a "DETACH" netbeans message in the command queue in order to |
2788 * terminate the netbeans session later. Do not end the session here | 2789 * terminate the netbeans session later. Do not end the session here |
2789 * directly as we may be running in the context of a call to | 2790 * directly as we may be running in the context of a call to |
2790 * netbeans_parse_messages(): | 2791 * netbeans_parse_messages(): |
2798 if (channel->ch_nb_close_cb != NULL) | 2799 if (channel->ch_nb_close_cb != NULL) |
2799 channel_save(channel, PART_OUT, (char_u *)DETACH_MSG_RAW, | 2800 channel_save(channel, PART_OUT, (char_u *)DETACH_MSG_RAW, |
2800 (int)STRLEN(DETACH_MSG_RAW), FALSE, "PUT "); | 2801 (int)STRLEN(DETACH_MSG_RAW), FALSE, "PUT "); |
2801 | 2802 |
2802 /* When reading from stdout is not possible, assume the other side has | 2803 /* When reading from stdout is not possible, assume the other side has |
2803 * died. */ | 2804 * died. Don't close the channel right away, it may be the wrong moment |
2805 * to invoke callbacks. */ | |
2806 channel->ch_to_be_closed = TRUE; | |
2807 } | |
2808 | |
2809 static void | |
2810 channel_close_now(channel_T *channel) | |
2811 { | |
2812 ch_log(channel, "Closing channel because of previous read error"); | |
2804 channel_close(channel, TRUE); | 2813 channel_close(channel, TRUE); |
2805 if (channel->ch_nb_close_cb != NULL) | 2814 if (channel->ch_nb_close_cb != NULL) |
2806 (*channel->ch_nb_close_cb)(); | 2815 (*channel->ch_nb_close_cb)(); |
2807 } | 2816 } |
2808 | 2817 |
3513 ch_log(NULL, "looking for messages on channels"); | 3522 ch_log(NULL, "looking for messages on channels"); |
3514 did_log_msg = FALSE; | 3523 did_log_msg = FALSE; |
3515 } | 3524 } |
3516 while (channel != NULL) | 3525 while (channel != NULL) |
3517 { | 3526 { |
3527 if (channel->ch_to_be_closed) | |
3528 { | |
3529 channel->ch_to_be_closed = FALSE; | |
3530 channel_close_now(channel); | |
3531 /* channel may have been freed, start over */ | |
3532 channel = first_channel; | |
3533 continue; | |
3534 } | |
3518 if (channel->ch_refcount == 0 && !channel_still_useful(channel)) | 3535 if (channel->ch_refcount == 0 && !channel_still_useful(channel)) |
3519 { | 3536 { |
3520 /* channel is no longer useful, free it */ | 3537 /* channel is no longer useful, free it */ |
3521 channel_free(channel); | 3538 channel_free(channel); |
3522 channel = first_channel; | 3539 channel = first_channel; |