Skip to content

Commit f336061

Browse files
committed
patch 8.0.1170: using termdebug results in 100% CPU time
Problem: Using termdebug results in 100% CPU time. (tomleb) Solution: Use polling instead of select().
1 parent 5ece3e3 commit f336061

File tree

4 files changed

+71
-15
lines changed

4 files changed

+71
-15
lines changed

src/channel.c

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3960,14 +3960,16 @@ ch_raw_common(typval_T *argvars, typval_T *rettv, int eval)
39603960
free_job_options(&opt);
39613961
}
39623962

3963+
# define KEEP_OPEN_TIME 20 /* msec */
3964+
39633965
# if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO)
39643966
/*
39653967
* Add open channels to the poll struct.
39663968
* Return the adjusted struct index.
39673969
* The type of "fds" is hidden to avoid problems with the function proto.
39683970
*/
39693971
int
3970-
channel_poll_setup(int nfd_in, void *fds_in)
3972+
channel_poll_setup(int nfd_in, void *fds_in, int *towait)
39713973
{
39723974
int nfd = nfd_in;
39733975
channel_T *channel;
@@ -3982,10 +3984,21 @@ channel_poll_setup(int nfd_in, void *fds_in)
39823984

39833985
if (ch_part->ch_fd != INVALID_FD)
39843986
{
3985-
ch_part->ch_poll_idx = nfd;
3986-
fds[nfd].fd = ch_part->ch_fd;
3987-
fds[nfd].events = POLLIN;
3988-
nfd++;
3987+
if (channel->ch_keep_open)
3988+
{
3989+
/* For unknown reason poll() returns immediately for a
3990+
* keep-open channel. Instead of adding it to the fds add
3991+
* a short timeout and check, like polling. */
3992+
if (*towait < 0 || *towait > KEEP_OPEN_TIME)
3993+
*towait = KEEP_OPEN_TIME;
3994+
}
3995+
else
3996+
{
3997+
ch_part->ch_poll_idx = nfd;
3998+
fds[nfd].fd = ch_part->ch_fd;
3999+
fds[nfd].events = POLLIN;
4000+
nfd++;
4001+
}
39894002
}
39904003
else
39914004
channel->ch_part[part].ch_poll_idx = -1;
@@ -4021,6 +4034,12 @@ channel_poll_check(int ret_in, void *fds_in)
40214034
channel_read(channel, part, "channel_poll_check");
40224035
--ret;
40234036
}
4037+
else if (channel->ch_part[part].ch_fd != INVALID_FD
4038+
&& channel->ch_keep_open)
4039+
{
4040+
/* polling a keep-open channel */
4041+
channel_read(channel, part, "channel_poll_check_keep_open");
4042+
}
40244043
}
40254044

40264045
in_part = &channel->ch_part[PART_IN];
@@ -4037,11 +4056,17 @@ channel_poll_check(int ret_in, void *fds_in)
40374056
# endif /* UNIX && !HAVE_SELECT */
40384057

40394058
# if (!defined(WIN32) && defined(HAVE_SELECT)) || defined(PROTO)
4059+
40404060
/*
40414061
* The "fd_set" type is hidden to avoid problems with the function proto.
40424062
*/
40434063
int
4044-
channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in)
4064+
channel_select_setup(
4065+
int maxfd_in,
4066+
void *rfds_in,
4067+
void *wfds_in,
4068+
struct timeval *tv,
4069+
struct timeval **tvp)
40454070
{
40464071
int maxfd = maxfd_in;
40474072
channel_T *channel;
@@ -4057,9 +4082,25 @@ channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in)
40574082

40584083
if (fd != INVALID_FD)
40594084
{
4060-
FD_SET((int)fd, rfds);
4061-
if (maxfd < (int)fd)
4062-
maxfd = (int)fd;
4085+
if (channel->ch_keep_open)
4086+
{
4087+
/* For unknown reason select() returns immediately for a
4088+
* keep-open channel. Instead of adding it to the rfds add
4089+
* a short timeout and check, like polling. */
4090+
if (*tvp == NULL || tv->tv_sec > 0
4091+
|| tv->tv_usec > KEEP_OPEN_TIME * 1000)
4092+
{
4093+
*tvp = tv;
4094+
tv->tv_sec = 0;
4095+
tv->tv_usec = KEEP_OPEN_TIME * 1000;
4096+
}
4097+
}
4098+
else
4099+
{
4100+
FD_SET((int)fd, rfds);
4101+
if (maxfd < (int)fd)
4102+
maxfd = (int)fd;
4103+
}
40634104
}
40644105
}
40654106
}
@@ -4094,6 +4135,11 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in)
40944135
FD_CLR(fd, rfds);
40954136
--ret;
40964137
}
4138+
else if (fd != INVALID_FD && channel->ch_keep_open)
4139+
{
4140+
/* polling a keep-open channel */
4141+
channel_read(channel, part, "channel_select_check_keep_open");
4142+
}
40974143
}
40984144

40994145
in_part = &channel->ch_part[PART_IN];

src/os_unix.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5330,6 +5330,9 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)
53305330
channel = add_channel();
53315331
if (channel == NULL)
53325332
goto failed;
5333+
if (job->jv_tty_out != NULL)
5334+
ch_log(channel, "using pty %s on fd %d",
5335+
job->jv_tty_out, pty_master_fd);
53335336
}
53345337

53355338
BLOCK_SIGNALS(&curset);
@@ -5702,6 +5705,9 @@ mch_create_pty_channel(job_T *job, jobopt_T *options)
57025705
close(pty_master_fd);
57035706
return FAIL;
57045707
}
5708+
if (job->jv_tty_out != NULL)
5709+
ch_log(channel, "using pty %s on fd %d",
5710+
job->jv_tty_out, pty_master_fd);
57055711
job->jv_channel = channel; /* ch_refcount was set by add_channel() */
57065712
channel->ch_keep_open = TRUE;
57075713

@@ -5969,7 +5975,7 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted)
59695975
}
59705976
# endif
59715977
#ifdef FEAT_JOB_CHANNEL
5972-
nfd = channel_poll_setup(nfd, &fds);
5978+
nfd = channel_poll_setup(nfd, &fds, &towait);
59735979
#endif
59745980
if (interrupted != NULL)
59755981
*interrupted = FALSE;
@@ -6021,7 +6027,8 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted)
60216027
}
60226028
# endif
60236029
#ifdef FEAT_JOB_CHANNEL
6024-
if (ret > 0)
6030+
/* also call when ret == 0, we may be polling a keep-open channel */
6031+
if (ret >= 0)
60256032
ret = channel_poll_check(ret, &fds);
60266033
#endif
60276034

@@ -6097,7 +6104,7 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted)
60976104
}
60986105
# endif
60996106
# ifdef FEAT_JOB_CHANNEL
6100-
maxfd = channel_select_setup(maxfd, &rfds, &wfds);
6107+
maxfd = channel_select_setup(maxfd, &rfds, &wfds, &tv, &tvp);
61016108
# endif
61026109
if (interrupted != NULL)
61036110
*interrupted = FALSE;
@@ -6183,7 +6190,8 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted)
61836190
}
61846191
# endif
61856192
#ifdef FEAT_JOB_CHANNEL
6186-
if (ret > 0)
6193+
/* also call when ret == 0, we may be polling a keep-open channel */
6194+
if (ret >= 0)
61876195
ret = channel_select_check(ret, &rfds, &wfds);
61886196
#endif
61896197

src/proto/channel.pro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ void channel_set_nonblock(channel_T *channel, ch_part_T part);
4040
int channel_send(channel_T *channel, ch_part_T part, char_u *buf_arg, int len_arg, char *fun);
4141
void ch_expr_common(typval_T *argvars, typval_T *rettv, int eval);
4242
void ch_raw_common(typval_T *argvars, typval_T *rettv, int eval);
43-
int channel_poll_setup(int nfd_in, void *fds_in);
43+
int channel_poll_setup(int nfd_in, void *fds_in, int *towait);
4444
int channel_poll_check(int ret_in, void *fds_in);
45-
int channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in);
45+
int channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in, struct timeval *tv, struct timeval **tvp);
4646
int channel_select_check(int ret_in, void *rfds_in, void *wfds_in);
4747
int channel_parse_messages(void);
4848
int channel_any_readahead(void);

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,8 @@ static char *(features[]) =
761761

762762
static int included_patches[] =
763763
{ /* Add new patch number below this line */
764+
/**/
765+
1170,
764766
/**/
765767
1169,
766768
/**/

0 commit comments

Comments
 (0)