Cygwin: console: Fix "Bad file descriptor" error in script command.
- After the commit 72770148
, script command exits occasionally with
the error "Bad file descriptor" if it is started in console on Win7
and non-cygwin process is executed. This patch fixes the issue.
This commit is contained in:
parent
5755870f7c
commit
a533334581
|
@ -557,9 +557,11 @@ fhandler_console::read (void *pv, size_t& buflen)
|
|||
#define buf ((char *) pv)
|
||||
|
||||
int ret;
|
||||
acquire_attach_mutex (INFINITE);
|
||||
acquire_input_mutex (INFINITE);
|
||||
ret = process_input_message ();
|
||||
release_input_mutex ();
|
||||
release_attach_mutex ();
|
||||
switch (ret)
|
||||
{
|
||||
case input_error:
|
||||
|
@ -616,8 +618,6 @@ fhandler_console::process_input_message (void)
|
|||
if (!shared_console_info)
|
||||
return input_error;
|
||||
|
||||
acquire_attach_mutex (INFINITE);
|
||||
|
||||
termios *ti = &(get_ttyp ()->ti);
|
||||
|
||||
fhandler_console::input_states stat = input_processing;
|
||||
|
@ -627,7 +627,6 @@ fhandler_console::process_input_message (void)
|
|||
if (!PeekConsoleInputW (get_handle (), input_rec, INREC_SIZE, &total_read))
|
||||
{
|
||||
termios_printf ("PeekConsoleInput failed, %E");
|
||||
release_attach_mutex ();
|
||||
return input_error;
|
||||
}
|
||||
|
||||
|
@ -991,8 +990,9 @@ fhandler_console::process_input_message (void)
|
|||
out:
|
||||
/* Discard processed recored. */
|
||||
DWORD dummy;
|
||||
ReadConsoleInputW (get_handle (), input_rec, min (total_read, i+1), &dummy);
|
||||
release_attach_mutex ();
|
||||
DWORD discard_len = min (total_read, i + 1);
|
||||
if (discard_len)
|
||||
ReadConsoleInputW (get_handle (), input_rec, discard_len, &dummy);
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
|
|
@ -1032,6 +1032,22 @@ fhandler_fifo::select_except (select_stuff *ss)
|
|||
return s;
|
||||
}
|
||||
|
||||
extern HANDLE attach_mutex; /* Defined in fhandler_console.cc */
|
||||
|
||||
static inline void
|
||||
acquire_attach_mutex (DWORD t)
|
||||
{
|
||||
if (attach_mutex)
|
||||
WaitForSingleObject (attach_mutex, t);
|
||||
}
|
||||
|
||||
static inline void
|
||||
release_attach_mutex ()
|
||||
{
|
||||
if (attach_mutex)
|
||||
ReleaseMutex (attach_mutex);
|
||||
}
|
||||
|
||||
static int
|
||||
peek_console (select_record *me, bool)
|
||||
{
|
||||
|
@ -1057,10 +1073,14 @@ peek_console (select_record *me, bool)
|
|||
HANDLE h;
|
||||
set_handle_or_return_if_not_open (h, me);
|
||||
|
||||
acquire_attach_mutex (INFINITE);
|
||||
while (!fh->input_ready && !fh->get_cons_readahead_valid ())
|
||||
{
|
||||
if (fh->bg_check (SIGTTIN, true) <= bg_eof)
|
||||
{
|
||||
release_attach_mutex ();
|
||||
return me->read_ready = true;
|
||||
}
|
||||
else if (!PeekConsoleInputW (h, &irec, 1, &events_read) || !events_read)
|
||||
break;
|
||||
fh->acquire_input_mutex (INFINITE);
|
||||
|
@ -1070,10 +1090,12 @@ peek_console (select_record *me, bool)
|
|||
{
|
||||
set_sig_errno (EINTR);
|
||||
fh->release_input_mutex ();
|
||||
release_attach_mutex ();
|
||||
return -1;
|
||||
}
|
||||
fh->release_input_mutex ();
|
||||
}
|
||||
release_attach_mutex ();
|
||||
if (fh->input_ready || fh->get_cons_readahead_valid ())
|
||||
return me->read_ready = true;
|
||||
|
||||
|
@ -1087,18 +1109,87 @@ verify_console (select_record *me, fd_set *rfds, fd_set *wfds,
|
|||
return peek_console (me, true);
|
||||
}
|
||||
|
||||
static int console_startup (select_record *me, select_stuff *stuff);
|
||||
|
||||
static DWORD WINAPI
|
||||
thread_console (void *arg)
|
||||
{
|
||||
select_console_info *ci = (select_console_info *) arg;
|
||||
DWORD sleep_time = 0;
|
||||
bool looping = true;
|
||||
|
||||
while (looping)
|
||||
{
|
||||
for (select_record *s = ci->start; (s = s->next); )
|
||||
if (s->startup == console_startup)
|
||||
{
|
||||
if (peek_console (s, true))
|
||||
looping = false;
|
||||
if (ci->stop_thread)
|
||||
{
|
||||
select_printf ("stopping");
|
||||
looping = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!looping)
|
||||
break;
|
||||
cygwait (ci->bye, sleep_time >> 3);
|
||||
if (sleep_time < 80)
|
||||
++sleep_time;
|
||||
if (ci->stop_thread)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
console_startup (select_record *me, select_stuff *stuff)
|
||||
{
|
||||
fhandler_console *fh = (fhandler_console *) me->fh;
|
||||
if (wincap.has_con_24bit_colors ())
|
||||
fhandler_console::request_xterm_mode_input (true, fh->get_handle_set ());
|
||||
|
||||
select_console_info *ci = stuff->device_specific_console;
|
||||
if (ci->start)
|
||||
me->h = *(stuff->device_specific_console)->thread;
|
||||
else
|
||||
{
|
||||
ci->start = &stuff->start;
|
||||
ci->stop_thread = false;
|
||||
ci->bye = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
|
||||
ci->thread = new cygthread (thread_console, ci, "conssel");
|
||||
me->h = *ci->thread;
|
||||
if (!me->h)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
console_cleanup (select_record *me, select_stuff *stuff)
|
||||
{
|
||||
select_console_info *ci = stuff->device_specific_console;
|
||||
if (!ci)
|
||||
return;
|
||||
if (ci->thread)
|
||||
{
|
||||
ci->stop_thread = true;
|
||||
SetEvent (ci->bye);
|
||||
ci->thread->detach ();
|
||||
CloseHandle (ci->bye);
|
||||
}
|
||||
delete ci;
|
||||
stuff->device_specific_console = NULL;
|
||||
}
|
||||
|
||||
select_record *
|
||||
fhandler_console::select_read (select_stuff *ss)
|
||||
{
|
||||
if (!ss->device_specific_console
|
||||
&& (ss->device_specific_console = new select_console_info) == NULL)
|
||||
return NULL;
|
||||
|
||||
select_record *s = ss->start.next;
|
||||
if (!s->startup)
|
||||
{
|
||||
|
@ -1108,9 +1199,9 @@ fhandler_console::select_read (select_stuff *ss)
|
|||
}
|
||||
|
||||
s->peek = peek_console;
|
||||
s->h = get_handle ();
|
||||
s->read_selected = true;
|
||||
s->read_ready = input_ready || get_cons_readahead_valid ();
|
||||
s->cleanup = console_cleanup;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,11 @@ struct select_info
|
|||
select_info (): thread (NULL), stop_thread (0), start (NULL) {}
|
||||
};
|
||||
|
||||
struct select_console_info: public select_info
|
||||
{
|
||||
select_console_info (): select_info () {}
|
||||
};
|
||||
|
||||
struct select_pipe_info: public select_info
|
||||
{
|
||||
select_pipe_info (): select_info () {}
|
||||
|
@ -102,6 +107,7 @@ public:
|
|||
its objects in the descriptor lists, here's the place to be. This is
|
||||
mainly used to maintain a single thread for all fhandlers of a single
|
||||
type in the descriptor lists. */
|
||||
select_console_info *device_specific_console;
|
||||
select_pipe_info *device_specific_pipe;
|
||||
select_pipe_info *device_specific_ptys;
|
||||
select_fifo_info *device_specific_fifo;
|
||||
|
@ -115,6 +121,7 @@ public:
|
|||
|
||||
select_stuff (): return_on_signal (false), always_ready (false),
|
||||
windows_used (false), start (),
|
||||
device_specific_console (NULL),
|
||||
device_specific_pipe (NULL),
|
||||
device_specific_ptys (NULL),
|
||||
device_specific_fifo (NULL),
|
||||
|
|
Loading…
Reference in New Issue