From: Takashi Yano <takashi.yano@nifty.ne.jp>
To: cygwin@cygwin.com
Subject: Re: Cygwin hangs up if several keys are typed during outputting a lot of texts.
Date: Wed, 04 Mar 2015 11:36:00 -0000 [thread overview]
Message-ID: <20150304203407.14008531b0fb63ad5c19a33f@nifty.ne.jp> (raw)
In-Reply-To: <20150302144426.GK3213@calimero.vinschen.de>
[-- Attachment #1: Type: text/plain, Size: 1617 bytes --]
On Mon, 2 Mar 2015 15:44:26 +0100
Corinna Vinschen <corinna-cygwin@cygwin.com> wrote:
> > 1) Buffer of named pipe gets full-filled by a lot of data written
> > by slave side.
> > 2) WriteFile() in fhandler_pty_master::doecho(), which is called
> > from master side by key input, is blocked because the buffer
> > is full.
> > 3) If a handling to read from the pipe is in the same thread as
> > key input, the thread falls into deadlock.
> >
> > To check buffer space before WriteFile() is one idea,
> > but it is not smart, I suppose...
>
> I think that's not it. For testing I added code to convert the
> WriteFile calls in fhandler_pty_slave::write, fhandler_pty_master::doecho
> and fhandler_pty_slave::write to overlapped I/O and made sure to wait
> for the result after the output mutex has been released.
>
> This change has no effect at all. Looks like this needs some more
> digging.
Hmm.
To confirm my assumption, I have modified the TTY code
for testing. The modification is shown in an attached
diff-file against current CVS version. (Note that this
patch is not for fixing the problem. It is for just a
testing.)
With this modification, half of buffer is kept empty
for fhandler_pty_master::doecho(). I assumed the blocking
could be avoided because buffer is always free.
As a result of the test, it has become clear that this
modification conceals the problem. This means the problem
is closely related to occupancy of buffer.
Now, I suppose the cause has been clarified. So we have
to work out a solution. How can we resolve this problem?
--
Takashi Yano <takashi.yano@nifty.ne.jp>
[-- Attachment #2: cygwin-test.patch.20150304 --]
[-- Type: application/octet-stream, Size: 7665 bytes --]
Index: src/winsup/cygwin/fhandler.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler.h,v
retrieving revision 1.513
diff -u -p -r1.513 fhandler.h
--- src/winsup/cygwin/fhandler.h 24 Feb 2015 11:05:02 -0000 1.513
+++ src/winsup/cygwin/fhandler.h 4 Mar 2015 11:01:27 -0000
@@ -1512,6 +1512,7 @@ class fhandler_pty_common: public fhandl
class fhandler_pty_slave: public fhandler_pty_common
{
HANDLE inuse; // used to indicate that a tty is in use
+ HANDLE from_slave, to_slave; // for testing
/* Helper functions for fchmod and fchown. */
bool fch_open_handles (bool chown);
Index: src/winsup/cygwin/fhandler_tty.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_tty.cc,v
retrieving revision 1.290
diff -u -p -r1.290 fhandler_tty.cc
--- src/winsup/cygwin/fhandler_tty.cc 25 Feb 2015 16:46:57 -0000 1.290
+++ src/winsup/cygwin/fhandler_tty.cc 4 Mar 2015 11:01:27 -0000
@@ -42,6 +42,8 @@ struct pipe_request {
struct pipe_reply {
HANDLE from_master;
HANDLE to_master;
+ HANDLE from_slave;
+ HANDLE to_slave;
DWORD error;
};
@@ -378,7 +380,8 @@ out:
/* pty slave stuff */
fhandler_pty_slave::fhandler_pty_slave (int unit)
- : fhandler_pty_common (), inuse (NULL)
+ : fhandler_pty_common (), inuse (NULL),
+ from_slave (NULL), to_slave (NULL)
{
if (unit >= 0)
dev ().parse (DEV_PTYS_MAJOR, unit);
@@ -388,10 +391,12 @@ int
fhandler_pty_slave::open (int flags, mode_t)
{
HANDLE pty_owner, from_master_local, to_master_local;
+ HANDLE from_slave_local, to_slave_local;
HANDLE *handles[] =
{
&from_master_local, &input_available_event, &input_mutex, &inuse,
&output_mutex, &to_master_local, &pty_owner,
+ &from_slave_local, &to_slave_local,
NULL
};
@@ -500,6 +505,22 @@ fhandler_pty_slave::open (int flags, mod
errmsg = "can't duplicate output, %E";
goto err;
}
+ if (!DuplicateHandle (pty_owner, get_ttyp ()->from_slave (),
+ GetCurrentProcess (), &from_slave_local, 0, TRUE,
+ DUPLICATE_SAME_ACCESS))
+ {
+ termios_printf ("can't duplicate master input from %u/%p, %E",
+ get_ttyp ()->master_pid, get_ttyp ()->from_slave ());
+ __seterrno ();
+ goto err_no_msg;
+ }
+ if (!DuplicateHandle (pty_owner, get_ttyp ()->to_slave (),
+ GetCurrentProcess (), &to_slave_local, 0, TRUE,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errmsg = "can't duplicate master output, %E";
+ goto err;
+ }
if (pty_owner != GetCurrentProcess ())
CloseHandle (pty_owner);
}
@@ -520,23 +541,39 @@ fhandler_pty_slave::open (int flags, mod
}
from_master_local = repl.from_master;
to_master_local = repl.to_master;
+ from_slave_local = repl.from_slave;
+ to_slave_local = repl.to_slave;
if (!from_master_local || !to_master_local)
{
SetLastError (repl.error);
errmsg = "error duplicating pipes, %E";
goto err;
}
+ if (!from_slave_local || !to_slave_local)
+ {
+ SetLastError (repl.error);
+ errmsg = "error duplicating master pipes, %E";
+ goto err;
+ }
}
VerifyHandle (from_master_local);
VerifyHandle (to_master_local);
+ VerifyHandle (from_slave_local);
+ VerifyHandle (to_slave_local);
termios_printf ("duplicated from_master %p->%p from pty_owner",
get_ttyp ()->from_master (), from_master_local);
termios_printf ("duplicated to_master %p->%p from pty_owner",
get_ttyp ()->to_master (), to_master_local);
+ termios_printf ("duplicated from_slave %p->%p from pty_owner",
+ get_ttyp ()->from_slave (), from_slave_local);
+ termios_printf ("duplicated to_slave %p->%p from pty_owner",
+ get_ttyp ()->to_slave (), to_slave_local);
set_io_handle (from_master_local);
set_output_handle (to_master_local);
+ from_slave = from_slave_local;
+ to_slave = to_slave_local;
fhandler_console::need_invisible ();
set_open_status ();
@@ -587,6 +624,10 @@ fhandler_pty_slave::close ()
termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event);
if ((unsigned) myself->ctty == FHDEV (DEV_PTYS_MAJOR, get_minor ()))
fhandler_console::free_console (); /* assumes that we are the last pty closer */
+ if (!ForceCloseHandle (from_slave))
+ termios_printf ("error closing from_slave %p, %E", from_slave);
+ if (!ForceCloseHandle (to_slave))
+ termios_printf ("error closing to_slave %p, %E", to_slave);
return fhandler_pty_common::close ();
}
@@ -653,6 +694,28 @@ fhandler_pty_slave::write (const void *p
while (tc ()->output_stopped)
cygwait (10);
+
+ /* for testing */
+ DWORD buflen;
+ if (!GetNamedPipeInfo (get_output_handle (), NULL, &buflen, NULL, NULL))
+ {
+ termios_printf ("GetNamedPipeInfo(%p) failed, %E", get_output_handle ());
+ buflen = fhandler_pty_common::pipesize;
+ }
+ DWORD occupied;
+ if (!PeekNamedPipe (from_slave, NULL, 0, NULL, &occupied, NULL))
+ {
+ termios_printf ("PeekNamedPipe(%p) failed, %E", from_slave);
+ }
+ else
+ {
+ while (n + occupied > buflen / 2)
+ {
+ cygwait (10);
+ PeekNamedPipe (from_slave, NULL, 0, NULL, &occupied, NULL);
+ }
+ }
+
acquire_output_mutex (INFINITE);
/* Previous write may have set write_error to != 0. Check it here.
@@ -1597,6 +1660,20 @@ fhandler_pty_master::pty_master_thread (
termios_printf ("DuplicateHandle (to_master), %E");
goto reply;
}
+ if (!DuplicateHandle (GetCurrentProcess (), get_io_handle (),
+ client, &repl.from_slave,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ {
+ termios_printf ("DuplicateHandle (from_slave), %E");
+ goto reply;
+ }
+ if (!DuplicateHandle (GetCurrentProcess (), get_output_handle (),
+ client, &repl.to_slave,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ {
+ termios_printf ("DuplicateHandle (to_slave), %E");
+ goto reply;
+ }
}
reply:
repl.error = GetLastError ();
@@ -1711,6 +1788,8 @@ fhandler_pty_master::setup ()
t.set_from_master (from_master);
t.set_to_master (to_master);
+ t.set_from_slave (get_io_handle ());
+ t.set_to_slave (get_output_handle ());
t.winsize.ws_col = 80;
t.winsize.ws_row = 25;
t.master_pid = myself->pid;
Index: src/winsup/cygwin/tty.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/tty.h,v
retrieving revision 1.37
diff -u -p -r1.37 tty.h
--- src/winsup/cygwin/tty.h 23 Apr 2013 09:44:34 -0000 1.37
+++ src/winsup/cygwin/tty.h 4 Mar 2015 11:01:27 -0000
@@ -104,15 +104,29 @@ private:
HANDLE _to_master;
LARGE_INTEGER _tm_dummy;
};
+ union {
+ HANDLE _from_slave;
+ LARGE_INTEGER _fs_dummy;
+ };
+ union {
+ HANDLE _to_slave;
+ LARGE_INTEGER _ts_dummy;
+ };
public:
HANDLE from_master() const { return _from_master; }
HANDLE to_master() const { return _to_master; }
+ HANDLE from_slave() const { return _from_slave; }
+ HANDLE to_slave() const { return _to_slave; }
#ifdef __x86_64__
void set_from_master (HANDLE h) { _from_master = h; }
void set_to_master (HANDLE h) { _to_master = h; }
+ void set_from_slave (HANDLE h) { _from_slave = h; }
+ void set_to_slave (HANDLE h) { _to_slave = h; }
#else
void set_from_master (HANDLE h) { _fm_dummy.HighPart = 0; _from_master = h; }
void set_to_master (HANDLE h) { _tm_dummy.HighPart = 0; _to_master = h; }
+ void set_from_slave (HANDLE h) { _fs_dummy.HighPart = 0; _from_slave = h; }
+ void set_to_slave (HANDLE h) { _ts_dummy.HighPart = 0; _to_slave = h; }
#endif
int read_retval;
[-- Attachment #3: Type: text/plain, Size: 218 bytes --]
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
next prev parent reply other threads:[~2015-03-04 11:33 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-28 12:40 Takashi Yano
2015-02-28 13:16 ` Denis Excoffier
2015-02-28 17:56 ` Corinna Vinschen
2015-03-02 11:45 ` Takashi Yano
2015-03-02 14:44 ` Corinna Vinschen
2015-03-02 14:50 ` Corinna Vinschen
2015-03-04 11:36 ` Takashi Yano [this message]
2015-03-04 12:43 ` Corinna Vinschen
2015-03-04 18:22 ` Corinna Vinschen
2015-03-04 20:25 ` Corinna Vinschen
2015-03-05 12:12 ` Takashi Yano
2015-03-05 13:31 ` Corinna Vinschen
2015-04-03 4:07 ` Takashi Yano
2015-04-03 4:19 ` Takashi Yano
2015-04-03 11:32 ` Corinna Vinschen
2015-04-04 6:55 ` Takashi Yano
2015-04-04 8:43 ` Corinna Vinschen
2015-04-05 11:54 ` Takashi Yano
2015-04-07 9:11 ` Corinna Vinschen
2015-04-13 10:31 ` Takashi Yano
2015-04-14 7:35 ` Corinna Vinschen
2015-04-16 0:26 ` Takashi Yano
2015-04-16 9:05 ` Corinna Vinschen
2015-04-16 9:10 ` Corinna Vinschen
2015-04-17 11:27 ` Takashi Yano
2015-04-17 12:10 ` Corinna Vinschen
2015-04-17 12:25 ` Corinna Vinschen
2015-04-20 11:40 ` Takashi Yano
2015-04-20 15:12 ` Corinna Vinschen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150304203407.14008531b0fb63ad5c19a33f@nifty.ne.jp \
--to=takashi.yano@nifty.ne.jp \
--cc=cygwin@cygwin.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).