mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-19 12:59:21 +08:00
Cygwin: console: Share readahead buffer within the same process.
- The cause of the problem reported in https://www.cygwin.com/ml/cygwin/2020-01/msg00220.html is that the chars input before dup() cannot be read from the new file descriptor. This is because the readahead buffer (rabuf) in the console is newly created by dup(), and does not inherit from the parent. This patch fixes the issue.
This commit is contained in:
parent
7d68ffadd3
commit
5ba41ad6e9
@ -44,11 +44,11 @@ void
|
|||||||
fhandler_base::reset (const fhandler_base *from)
|
fhandler_base::reset (const fhandler_base *from)
|
||||||
{
|
{
|
||||||
pc << from->pc;
|
pc << from->pc;
|
||||||
rabuf = NULL;
|
ra.rabuf = NULL;
|
||||||
ralen = 0;
|
ra.ralen = 0;
|
||||||
raixget = 0;
|
ra.raixget = 0;
|
||||||
raixput = 0;
|
ra.raixput = 0;
|
||||||
rabuflen = 0;
|
ra.rabuflen = 0;
|
||||||
_refcnt = 0;
|
_refcnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,15 +66,15 @@ int
|
|||||||
fhandler_base::put_readahead (char value)
|
fhandler_base::put_readahead (char value)
|
||||||
{
|
{
|
||||||
char *newrabuf;
|
char *newrabuf;
|
||||||
if (raixput < rabuflen)
|
if (raixput () < rabuflen ())
|
||||||
/* Nothing to do */;
|
/* Nothing to do */;
|
||||||
else if ((newrabuf = (char *) realloc (rabuf, rabuflen += 32)))
|
else if ((newrabuf = (char *) realloc (rabuf (), rabuflen () += 32)))
|
||||||
rabuf = newrabuf;
|
rabuf () = newrabuf;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rabuf[raixput++] = value;
|
rabuf ()[raixput ()++] = value;
|
||||||
ralen++;
|
ralen ()++;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,11 +82,11 @@ int
|
|||||||
fhandler_base::get_readahead ()
|
fhandler_base::get_readahead ()
|
||||||
{
|
{
|
||||||
int chret = -1;
|
int chret = -1;
|
||||||
if (raixget < ralen)
|
if (raixget () < ralen ())
|
||||||
chret = ((unsigned char) rabuf[raixget++]) & 0xff;
|
chret = ((unsigned char) rabuf ()[raixget ()++]) & 0xff;
|
||||||
/* FIXME - not thread safe */
|
/* FIXME - not thread safe */
|
||||||
if (raixget >= ralen)
|
if (raixget () >= ralen ())
|
||||||
raixget = raixput = ralen = 0;
|
raixget () = raixput () = ralen () = 0;
|
||||||
return chret;
|
return chret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,10 +94,10 @@ int
|
|||||||
fhandler_base::peek_readahead (int queryput)
|
fhandler_base::peek_readahead (int queryput)
|
||||||
{
|
{
|
||||||
int chret = -1;
|
int chret = -1;
|
||||||
if (!queryput && raixget < ralen)
|
if (!queryput && raixget () < ralen ())
|
||||||
chret = ((unsigned char) rabuf[raixget]) & 0xff;
|
chret = ((unsigned char) rabuf ()[raixget ()]) & 0xff;
|
||||||
else if (queryput && raixput > 0)
|
else if (queryput && raixput () > 0)
|
||||||
chret = ((unsigned char) rabuf[raixput - 1]) & 0xff;
|
chret = ((unsigned char) rabuf ()[raixput () - 1]) & 0xff;
|
||||||
return chret;
|
return chret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ void
|
|||||||
fhandler_base::set_readahead_valid (int val, int ch)
|
fhandler_base::set_readahead_valid (int val, int ch)
|
||||||
{
|
{
|
||||||
if (!val)
|
if (!val)
|
||||||
ralen = raixget = raixput = 0;
|
ralen () = raixget () = raixput () = 0;
|
||||||
if (ch != -1)
|
if (ch != -1)
|
||||||
put_readahead (ch);
|
put_readahead (ch);
|
||||||
}
|
}
|
||||||
@ -1092,7 +1092,7 @@ fhandler_base::lseek (off_t offset, int whence)
|
|||||||
if (whence != SEEK_CUR || offset != 0)
|
if (whence != SEEK_CUR || offset != 0)
|
||||||
{
|
{
|
||||||
if (whence == SEEK_CUR)
|
if (whence == SEEK_CUR)
|
||||||
offset -= ralen - raixget;
|
offset -= ralen () - raixget ();
|
||||||
set_readahead_valid (0);
|
set_readahead_valid (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1142,7 +1142,7 @@ fhandler_base::lseek (off_t offset, int whence)
|
|||||||
readahead that we have to take into account when calculating
|
readahead that we have to take into account when calculating
|
||||||
the actual position for the application. */
|
the actual position for the application. */
|
||||||
if (whence == SEEK_CUR)
|
if (whence == SEEK_CUR)
|
||||||
res -= ralen - raixget;
|
res -= ralen () - raixget ();
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -1565,23 +1565,23 @@ fhandler_base::fhandler_base () :
|
|||||||
ino (0),
|
ino (0),
|
||||||
_refcnt (0),
|
_refcnt (0),
|
||||||
openflags (0),
|
openflags (0),
|
||||||
rabuf (NULL),
|
|
||||||
ralen (0),
|
|
||||||
raixget (0),
|
|
||||||
raixput (0),
|
|
||||||
rabuflen (0),
|
|
||||||
unique_id (0),
|
unique_id (0),
|
||||||
archetype (NULL),
|
archetype (NULL),
|
||||||
usecount (0)
|
usecount (0)
|
||||||
{
|
{
|
||||||
|
ra.rabuf = NULL;
|
||||||
|
ra.ralen = 0;
|
||||||
|
ra.raixget = 0;
|
||||||
|
ra.raixput = 0;
|
||||||
|
ra.rabuflen = 0;
|
||||||
isclosed (false);
|
isclosed (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Normal I/O destructor */
|
/* Normal I/O destructor */
|
||||||
fhandler_base::~fhandler_base ()
|
fhandler_base::~fhandler_base ()
|
||||||
{
|
{
|
||||||
if (rabuf)
|
if (ra.rabuf)
|
||||||
free (rabuf);
|
free (ra.rabuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
@ -202,16 +202,21 @@ class fhandler_base
|
|||||||
|
|
||||||
ino_t ino; /* file ID or hashed filename, depends on FS. */
|
ino_t ino; /* file ID or hashed filename, depends on FS. */
|
||||||
LONG _refcnt;
|
LONG _refcnt;
|
||||||
|
public:
|
||||||
|
struct rabuf_t
|
||||||
|
{
|
||||||
|
char *rabuf; /* used for crlf conversion in text files */
|
||||||
|
size_t ralen;
|
||||||
|
size_t raixget;
|
||||||
|
size_t raixput;
|
||||||
|
size_t rabuflen;
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* File open flags from open () and fcntl () calls */
|
/* File open flags from open () and fcntl () calls */
|
||||||
int openflags;
|
int openflags;
|
||||||
|
|
||||||
char *rabuf; /* used for crlf conversion in text files */
|
struct rabuf_t ra;
|
||||||
size_t ralen;
|
|
||||||
size_t raixget;
|
|
||||||
size_t raixput;
|
|
||||||
size_t rabuflen;
|
|
||||||
|
|
||||||
/* Used for advisory file locking. See flock.cc. */
|
/* Used for advisory file locking. See flock.cc. */
|
||||||
int64_t unique_id;
|
int64_t unique_id;
|
||||||
@ -315,7 +320,13 @@ class fhandler_base
|
|||||||
ReleaseSemaphore (read_state, n, NULL);
|
ReleaseSemaphore (read_state, n, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_readahead_valid () { return raixget < ralen; }
|
virtual char *&rabuf () { return ra.rabuf; };
|
||||||
|
virtual size_t &ralen () { return ra.ralen; };
|
||||||
|
virtual size_t &raixget () { return ra.raixget; };
|
||||||
|
virtual size_t &raixput () { return ra.raixput; };
|
||||||
|
virtual size_t &rabuflen () { return ra.rabuflen; };
|
||||||
|
|
||||||
|
bool get_readahead_valid () { return raixget () < ralen (); }
|
||||||
int puts_readahead (const char *s, size_t len = (size_t) -1);
|
int puts_readahead (const char *s, size_t len = (size_t) -1);
|
||||||
int put_readahead (char value);
|
int put_readahead (char value);
|
||||||
|
|
||||||
@ -464,8 +475,8 @@ public:
|
|||||||
virtual bg_check_types bg_check (int, bool = false) {return bg_ok;}
|
virtual bg_check_types bg_check (int, bool = false) {return bg_ok;}
|
||||||
virtual void clear_readahead ()
|
virtual void clear_readahead ()
|
||||||
{
|
{
|
||||||
raixput = raixget = ralen = rabuflen = 0;
|
raixput () = raixget () = ralen () = rabuflen () = 0;
|
||||||
rabuf = NULL;
|
rabuf () = NULL;
|
||||||
}
|
}
|
||||||
void operator delete (void *p) {cfree (p);}
|
void operator delete (void *p) {cfree (p);}
|
||||||
virtual void set_eof () {}
|
virtual void set_eof () {}
|
||||||
@ -2051,6 +2062,12 @@ private:
|
|||||||
DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms);
|
DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms);
|
||||||
void __release_output_mutex (const char *fn, int ln);
|
void __release_output_mutex (const char *fn, int ln);
|
||||||
|
|
||||||
|
char *&rabuf ();
|
||||||
|
size_t &ralen ();
|
||||||
|
size_t &raixget ();
|
||||||
|
size_t &raixput ();
|
||||||
|
size_t &rabuflen ();
|
||||||
|
|
||||||
friend tty_min * tty_list::get_cttyp ();
|
friend tty_min * tty_list::get_cttyp ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,6 +56,10 @@ bool NO_COPY fhandler_console::invisible_console;
|
|||||||
static DWORD orig_conin_mode = (DWORD) -1;
|
static DWORD orig_conin_mode = (DWORD) -1;
|
||||||
static DWORD orig_conout_mode = (DWORD) -1;
|
static DWORD orig_conout_mode = (DWORD) -1;
|
||||||
|
|
||||||
|
/* con_ra is shared in the same process.
|
||||||
|
Only one console can exist in a process, therefore, static is suitable. */
|
||||||
|
static struct fhandler_base::rabuf_t con_ra;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
beep ()
|
beep ()
|
||||||
{
|
{
|
||||||
@ -214,6 +218,36 @@ fhandler_console::setup ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *&
|
||||||
|
fhandler_console::rabuf ()
|
||||||
|
{
|
||||||
|
return con_ra.rabuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t &
|
||||||
|
fhandler_console::ralen ()
|
||||||
|
{
|
||||||
|
return con_ra.ralen;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t &
|
||||||
|
fhandler_console::raixget ()
|
||||||
|
{
|
||||||
|
return con_ra.raixget;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t &
|
||||||
|
fhandler_console::raixput ()
|
||||||
|
{
|
||||||
|
return con_ra.raixput;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t &
|
||||||
|
fhandler_console::rabuflen ()
|
||||||
|
{
|
||||||
|
return con_ra.rabuflen;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the tty structure associated with a given tty number. If the
|
/* Return the tty structure associated with a given tty number. If the
|
||||||
tty number is < 0, just return a dummy record. */
|
tty number is < 0, just return a dummy record. */
|
||||||
tty_min *
|
tty_min *
|
||||||
@ -454,7 +488,7 @@ fhandler_console::read (void *pv, size_t& buflen)
|
|||||||
copied_chars +=
|
copied_chars +=
|
||||||
get_readahead_into_buffer (buf + copied_chars, buflen);
|
get_readahead_into_buffer (buf + copied_chars, buflen);
|
||||||
|
|
||||||
if (!ralen)
|
if (!con_ra.ralen)
|
||||||
input_ready = false;
|
input_ready = false;
|
||||||
release_input_mutex ();
|
release_input_mutex ();
|
||||||
|
|
||||||
@ -1103,6 +1137,9 @@ fhandler_console::close ()
|
|||||||
CloseHandle (get_handle ());
|
CloseHandle (get_handle ());
|
||||||
CloseHandle (get_output_handle ());
|
CloseHandle (get_output_handle ());
|
||||||
|
|
||||||
|
if (con_ra.rabuf)
|
||||||
|
free (con_ra.rabuf);
|
||||||
|
|
||||||
/* If already attached to pseudo console, don't call free_console () */
|
/* If already attached to pseudo console, don't call free_console () */
|
||||||
cygheap_fdenum cfd (false);
|
cygheap_fdenum cfd (false);
|
||||||
while (cfd.next () >= 0)
|
while (cfd.next () >= 0)
|
||||||
|
@ -265,25 +265,26 @@ fhandler_termios::bg_check (int sig, bool dontsignal)
|
|||||||
int
|
int
|
||||||
fhandler_termios::eat_readahead (int n)
|
fhandler_termios::eat_readahead (int n)
|
||||||
{
|
{
|
||||||
int oralen = ralen;
|
int oralen = ralen ();
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
n = ralen;
|
n = ralen ();
|
||||||
if (n > 0 && ralen > 0)
|
if (n > 0 && ralen () > 0)
|
||||||
{
|
{
|
||||||
if ((int) (ralen -= n) < 0)
|
if ((int) (ralen () -= n) < 0)
|
||||||
ralen = 0;
|
ralen () = 0;
|
||||||
/* If IUTF8 is set, the terminal is in UTF-8 mode. If so, we erase
|
/* If IUTF8 is set, the terminal is in UTF-8 mode. If so, we erase
|
||||||
a complete UTF-8 multibyte sequence on VERASE/VWERASE. Otherwise,
|
a complete UTF-8 multibyte sequence on VERASE/VWERASE. Otherwise,
|
||||||
if we only erase a single byte, invalid unicode chars are left in
|
if we only erase a single byte, invalid unicode chars are left in
|
||||||
the input. */
|
the input. */
|
||||||
if (tc ()->ti.c_iflag & IUTF8)
|
if (tc ()->ti.c_iflag & IUTF8)
|
||||||
while (ralen > 0 && ((unsigned char) rabuf[ralen] & 0xc0) == 0x80)
|
while (ralen () > 0 &&
|
||||||
--ralen;
|
((unsigned char) rabuf ()[ralen ()] & 0xc0) == 0x80)
|
||||||
|
--ralen ();
|
||||||
|
|
||||||
if (raixget >= ralen)
|
if (raixget () >= ralen ())
|
||||||
raixget = raixput = ralen = 0;
|
raixget () = raixput () = ralen () = 0;
|
||||||
else if (raixput > ralen)
|
else if (raixput () > ralen ())
|
||||||
raixput = ralen;
|
raixput () = ralen ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return oralen;
|
return oralen;
|
||||||
@ -411,7 +412,7 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
|
|||||||
if (ti.c_lflag & ECHO)
|
if (ti.c_lflag & ECHO)
|
||||||
{
|
{
|
||||||
doecho ("\n\r", 2);
|
doecho ("\n\r", 2);
|
||||||
doecho (rabuf, ralen);
|
doecho (rabuf (), ralen ());
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -438,13 +439,13 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
|
|||||||
doecho (&c, 1);
|
doecho (&c, 1);
|
||||||
/* Write in chunks of 32 bytes to reduce the number of WriteFile calls
|
/* Write in chunks of 32 bytes to reduce the number of WriteFile calls
|
||||||
in non-canonical mode. */
|
in non-canonical mode. */
|
||||||
if ((!iscanon && ralen >= 32) || input_done)
|
if ((!iscanon && ralen () >= 32) || input_done)
|
||||||
{
|
{
|
||||||
int status = accept_input ();
|
int status = accept_input ();
|
||||||
if (status != 1)
|
if (status != 1)
|
||||||
{
|
{
|
||||||
ret = status ? line_edit_error : line_edit_pipe_full;
|
ret = status ? line_edit_error : line_edit_pipe_full;
|
||||||
nread += ralen;
|
nread += ralen ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = line_edit_input_done;
|
ret = line_edit_input_done;
|
||||||
@ -453,14 +454,14 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If we didn't write all bytes in non-canonical mode, write them now. */
|
/* If we didn't write all bytes in non-canonical mode, write them now. */
|
||||||
if (!iscanon && ralen > 0
|
if (!iscanon && ralen () > 0
|
||||||
&& (ret == line_edit_ok || ret == line_edit_input_done))
|
&& (ret == line_edit_ok || ret == line_edit_input_done))
|
||||||
{
|
{
|
||||||
int status = accept_input ();
|
int status = accept_input ();
|
||||||
if (status != 1)
|
if (status != 1)
|
||||||
{
|
{
|
||||||
ret = status ? line_edit_error : line_edit_pipe_full;
|
ret = status ? line_edit_error : line_edit_pipe_full;
|
||||||
nread += ralen;
|
nread += ralen ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ret = line_edit_input_done;
|
ret = line_edit_input_done;
|
||||||
|
@ -525,7 +525,7 @@ fhandler_pty_master::accept_input ()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *p = rabuf;
|
char *p = rabuf ();
|
||||||
DWORD rc;
|
DWORD rc;
|
||||||
DWORD written = 0;
|
DWORD written = 0;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user