diff src/channel.c @ 12584:f28067b83dec v8.0.1170

patch 8.0.1170: using termdebug results in 100% CPU time commit https://github.com/vim/vim/commit/f33606112a59de6965692840b47d9cb4b924fc97 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Oct 1 16:21:31 2017 +0200 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().
author Christian Brabandt <cb@256bit.org>
date Sun, 01 Oct 2017 16:30:03 +0200
parents 579faede5d9c
children 60e1e4cfb21e
line wrap: on
line diff
--- a/src/channel.c
+++ b/src/channel.c
@@ -3960,6 +3960,8 @@ ch_raw_common(typval_T *argvars, typval_
     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_
  * 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
 
 	    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
 		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
 # 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 
 
 	    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 *r
 		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];