Mercurial > vim
comparison src/channel.c @ 13778:5f6c61a71c02 v8.0.1761
patch 8.0.1761: job in terminal window with no output channel is killed
commit https://github.com/vim/vim/commit/4e9d443a25b451e3f2de62e9eeea439aa4c3f039
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Apr 24 20:54:07 2018 +0200
patch 8.0.1761: job in terminal window with no output channel is killed
Problem: Job in terminal window with no output channel is killed.
Solution: Keep the job running when the input is a tty. (Ozaki Kiichi,
closes #2734)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Tue, 24 Apr 2018 21:00:07 +0200 |
parents | 3ab6198c1f9a |
children | c01864ecf233 |
comparison
equal
deleted
inserted
replaced
13777:bdecc420bd2c | 13778:5f6c61a71c02 |
---|---|
343 || channel->ch_part[PART_ERR].ch_bufref.br_buf != NULL) | 343 || channel->ch_part[PART_ERR].ch_bufref.br_buf != NULL) |
344 && has_err_msg); | 344 && has_err_msg); |
345 } | 345 } |
346 | 346 |
347 /* | 347 /* |
348 * Return TRUE if "channel" is closeable (i.e. all readable fds are closed). | |
349 */ | |
350 static int | |
351 channel_can_close(channel_T *channel) | |
352 { | |
353 return channel->ch_to_be_closed == 0; | |
354 } | |
355 | |
356 /* | |
348 * Close a channel and free all its resources. | 357 * Close a channel and free all its resources. |
349 */ | 358 */ |
350 static void | 359 static void |
351 channel_free_contents(channel_T *channel) | 360 channel_free_contents(channel_T *channel) |
352 { | 361 { |
890 | 899 |
891 channel->CH_SOCK_FD = (sock_T)sd; | 900 channel->CH_SOCK_FD = (sock_T)sd; |
892 channel->ch_nb_close_cb = nb_close_cb; | 901 channel->ch_nb_close_cb = nb_close_cb; |
893 channel->ch_hostname = (char *)vim_strsave((char_u *)hostname); | 902 channel->ch_hostname = (char *)vim_strsave((char_u *)hostname); |
894 channel->ch_port = port_in; | 903 channel->ch_port = port_in; |
895 channel->ch_to_be_closed |= (1 << PART_SOCK); | 904 channel->ch_to_be_closed |= (1U << PART_SOCK); |
896 | 905 |
897 #ifdef FEAT_GUI | 906 #ifdef FEAT_GUI |
898 channel_gui_register_one(channel, PART_SOCK); | 907 channel_gui_register_one(channel, PART_SOCK); |
899 #endif | 908 #endif |
900 | 909 |
986 fd_close(*fd); | 995 fd_close(*fd); |
987 } | 996 } |
988 } | 997 } |
989 *fd = INVALID_FD; | 998 *fd = INVALID_FD; |
990 | 999 |
991 channel->ch_to_be_closed &= ~(1 << part); | 1000 /* channel is closed, may want to end the job if it was the last */ |
1001 channel->ch_to_be_closed &= ~(1U << part); | |
992 } | 1002 } |
993 } | 1003 } |
994 | 1004 |
995 void | 1005 void |
996 channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err) | 1006 channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err) |
997 { | 1007 { |
998 if (in != INVALID_FD) | 1008 if (in != INVALID_FD) |
999 { | 1009 { |
1000 ch_close_part(channel, PART_IN); | 1010 ch_close_part(channel, PART_IN); |
1001 channel->CH_IN_FD = in; | 1011 channel->CH_IN_FD = in; |
1012 # if defined(UNIX) | |
1013 /* Do not end the job when all output channels are closed, wait until | |
1014 * the job ended. */ | |
1015 if (isatty(in)) | |
1016 channel->ch_to_be_closed |= (1U << PART_IN); | |
1017 # endif | |
1002 } | 1018 } |
1003 if (out != INVALID_FD) | 1019 if (out != INVALID_FD) |
1004 { | 1020 { |
1005 # if defined(FEAT_GUI) | 1021 # if defined(FEAT_GUI) |
1006 channel_gui_unregister_one(channel, PART_OUT); | 1022 channel_gui_unregister_one(channel, PART_OUT); |
1007 # endif | 1023 # endif |
1008 ch_close_part(channel, PART_OUT); | 1024 ch_close_part(channel, PART_OUT); |
1009 channel->CH_OUT_FD = out; | 1025 channel->CH_OUT_FD = out; |
1010 channel->ch_to_be_closed |= (1 << PART_OUT); | 1026 channel->ch_to_be_closed |= (1U << PART_OUT); |
1011 # if defined(FEAT_GUI) | 1027 # if defined(FEAT_GUI) |
1012 channel_gui_register_one(channel, PART_OUT); | 1028 channel_gui_register_one(channel, PART_OUT); |
1013 # endif | 1029 # endif |
1014 } | 1030 } |
1015 if (err != INVALID_FD) | 1031 if (err != INVALID_FD) |
1017 # if defined(FEAT_GUI) | 1033 # if defined(FEAT_GUI) |
1018 channel_gui_unregister_one(channel, PART_ERR); | 1034 channel_gui_unregister_one(channel, PART_ERR); |
1019 # endif | 1035 # endif |
1020 ch_close_part(channel, PART_ERR); | 1036 ch_close_part(channel, PART_ERR); |
1021 channel->CH_ERR_FD = err; | 1037 channel->CH_ERR_FD = err; |
1022 channel->ch_to_be_closed |= (1 << PART_ERR); | 1038 channel->ch_to_be_closed |= (1U << PART_ERR); |
1023 # if defined(FEAT_GUI) | 1039 # if defined(FEAT_GUI) |
1024 channel_gui_register_one(channel, PART_ERR); | 1040 channel_gui_register_one(channel, PART_ERR); |
1025 # endif | 1041 # endif |
1026 } | 1042 } |
1027 } | 1043 } |
4198 ch_log(NULL, "looking for messages on channels"); | 4214 ch_log(NULL, "looking for messages on channels"); |
4199 did_log_msg = FALSE; | 4215 did_log_msg = FALSE; |
4200 } | 4216 } |
4201 while (channel != NULL) | 4217 while (channel != NULL) |
4202 { | 4218 { |
4203 if (channel->ch_to_be_closed == 0) | 4219 if (channel_can_close(channel)) |
4204 { | 4220 { |
4205 channel->ch_to_be_closed = (1 << PART_COUNT); | 4221 channel->ch_to_be_closed = (1U << PART_COUNT); |
4206 channel_close_now(channel); | 4222 channel_close_now(channel); |
4207 /* channel may have been freed, start over */ | 4223 /* channel may have been freed, start over */ |
4208 channel = first_channel; | 4224 channel = first_channel; |
4209 continue; | 4225 continue; |
4210 } | 4226 } |
5078 { | 5094 { |
5079 return job->jv_channel != NULL && channel_still_useful(job->jv_channel); | 5095 return job->jv_channel != NULL && channel_still_useful(job->jv_channel); |
5080 } | 5096 } |
5081 | 5097 |
5082 /* | 5098 /* |
5099 * Return TRUE if the channel of "job" is closeable. | |
5100 */ | |
5101 static int | |
5102 job_channel_can_close(job_T *job) | |
5103 { | |
5104 return job->jv_channel != NULL && channel_can_close(job->jv_channel); | |
5105 } | |
5106 | |
5107 /* | |
5083 * Return TRUE if the job should not be freed yet. Do not free the job when | 5108 * Return TRUE if the job should not be freed yet. Do not free the job when |
5084 * it has not ended yet and there is a "stoponexit" flag, an exit callback | 5109 * it has not ended yet and there is a "stoponexit" flag, an exit callback |
5085 * or when the associated channel will do something with the job output. | 5110 * or when the associated channel will do something with the job output. |
5086 */ | 5111 */ |
5087 static int | 5112 static int |
5207 return; | 5232 return; |
5208 | 5233 |
5209 /* Ready to cleanup the job. */ | 5234 /* Ready to cleanup the job. */ |
5210 job->jv_status = JOB_FINISHED; | 5235 job->jv_status = JOB_FINISHED; |
5211 | 5236 |
5237 /* When only channel-in is kept open, close explicitly. */ | |
5238 if (job->jv_channel != NULL) | |
5239 ch_close_part(job->jv_channel, PART_IN); | |
5240 | |
5212 if (job->jv_exit_cb != NULL) | 5241 if (job->jv_exit_cb != NULL) |
5213 { | 5242 { |
5214 typval_T argv[3]; | 5243 typval_T argv[3]; |
5215 typval_T rettv; | 5244 typval_T rettv; |
5216 int dummy; | 5245 int dummy; |
5411 job_T *job; | 5440 job_T *job; |
5412 | 5441 |
5413 for (job = first_job; job != NULL; job = job->jv_next) | 5442 for (job = first_job; job != NULL; job = job->jv_next) |
5414 /* Only should check if the channel has been closed, if the channel is | 5443 /* Only should check if the channel has been closed, if the channel is |
5415 * open the job won't exit. */ | 5444 * open the job won't exit. */ |
5416 if (job->jv_status == JOB_STARTED && job->jv_exit_cb != NULL | 5445 if ((job->jv_status == JOB_STARTED && !job_channel_still_useful(job)) |
5417 && !job_channel_still_useful(job)) | 5446 || (job->jv_status == JOB_FINISHED |
5447 && job_channel_can_close(job))) | |
5418 return TRUE; | 5448 return TRUE; |
5419 return FALSE; | 5449 return FALSE; |
5420 } | 5450 } |
5421 | 5451 |
5422 #define MAX_CHECK_ENDED 8 | 5452 #define MAX_CHECK_ENDED 8 |