summaryrefslogtreecommitdiffstats
path: root/src/channel.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-10-01 16:21:31 +0200
committerBram Moolenaar <Bram@vim.org>2017-10-01 16:21:31 +0200
commitf33606112a59de6965692840b47d9cb4b924fc97 (patch)
tree14645c554f821e686128f5754b09c9be10909e8e /src/channel.c
parent5ece3e359c4b96d0f9bf1ce690223545f40f34b8 (diff)
patch 8.0.1170: using termdebug results in 100% CPU timev8.0.1170
Problem: Using termdebug results in 100% CPU time. (tomleb) Solution: Use polling instead of select().
Diffstat (limited to 'src/channel.c')
-rw-r--r--src/channel.c64
1 files changed, 55 insertions, 9 deletions
diff --git a/src/channel.c b/src/channel.c
index 49bab16d11..606c66a869 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -3960,6 +3960,8 @@ ch_raw_common(typval_T *argvars, typval_T *rettv, int eval)
free_job_options(&opt);
}
+# define KEEP_OPEN_TIME 20 /* msec */
+
# if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO)
/*
* Add open channels to the poll struct.
@@ -3967,7 +3969,7 @@ ch_raw_common(typval_T *argvars, typval_T *rettv, int eval)
* The type of "fds" is hidden to avoid problems with the function proto.
*/
int
-channel_poll_setup(int nfd_in, void *fds_in)
+channel_poll_setup(int nfd_in, void *fds_in, int *towait)
{
int nfd = nfd_in;
channel_T *channel;
@@ -3982,10 +3984,21 @@ channel_poll_setup(int nfd_in, void *fds_in)
if (ch_part->ch_fd != INVALID_FD)
{
- ch_part->ch_poll_idx = nfd;
- fds[nfd].fd = ch_part->ch_fd;
- fds[nfd].events = POLLIN;
- nfd++;
+ if (channel->ch_keep_open)
+ {
+ /* For unknown reason poll() returns immediately for a
+ * keep-open channel. Instead of adding it to the fds add
+ * a short timeout and check, like polling. */
+ if (*towait < 0 || *towait > KEEP_OPEN_TIME)
+ *towait = KEEP_OPEN_TIME;
+ }
+ else
+ {
+ ch_part->ch_poll_idx = nfd;
+ fds[nfd].fd = ch_part->ch_fd;
+ fds[nfd].events = POLLIN;
+ nfd++;
+ }
}
else
channel->ch_part[part].ch_poll_idx = -1;
@@ -4021,6 +4034,12 @@ channel_poll_check(int ret_in, void *fds_in)
channel_read(channel, part, "channel_poll_check");
--ret;
}
+ else if (channel->ch_part[part].ch_fd != INVALID_FD
+ && channel->ch_keep_open)
+ {
+ /* polling a keep-open channel */
+ channel_read(channel, part, "channel_poll_check_keep_open");
+ }
}
in_part = &channel->ch_part[PART_IN];
@@ -4037,11 +4056,17 @@ channel_poll_check(int ret_in, void *fds_in)
# endif /* UNIX && !HAVE_SELECT */
# if (!defined(WIN32) && defined(HAVE_SELECT)) || defined(PROTO)
+
/*
* The "fd_set" type is hidden to avoid problems with the function proto.
*/
int
-channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in)
+channel_select_setup(
+ int maxfd_in,
+ void *rfds_in,
+ void *wfds_in,
+ struct timeval *tv,
+ struct timeval **tvp)
{
int maxfd = maxfd_in;
channel_T *channel;
@@ -4057,9 +4082,25 @@ channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in)
if (fd != INVALID_FD)
{
- FD_SET((int)fd, rfds);
- if (maxfd < (int)fd)
- maxfd = (int)fd;
+ if (channel->ch_keep_open)
+ {
+ /* For unknown reason select() returns immediately for a
+ * keep-open channel. Instead of adding it to the rfds add
+ * a short timeout and check, like polling. */
+ if (*tvp == NULL || tv->tv_sec > 0
+ || tv->tv_usec > KEEP_OPEN_TIME * 1000)
+ {
+ *tvp = tv;
+ tv->tv_sec = 0;
+ tv->tv_usec = KEEP_OPEN_TIME * 1000;
+ }
+ }
+ else
+ {
+ FD_SET((int)fd, rfds);
+ if (maxfd < (int)fd)
+ maxfd = (int)fd;
+ }
}
}
}
@@ -4094,6 +4135,11 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in)
FD_CLR(fd, rfds);
--ret;
}
+ else if (fd != INVALID_FD && channel->ch_keep_open)
+ {
+ /* polling a keep-open channel */
+ channel_read(channel, part, "channel_select_check_keep_open");
+ }
}
in_part = &channel->ch_part[PART_IN];