mirror of
https://github.com/aphrody-labs/cygwin.git
synced 2026-10-13 22:03:45 +00:00
Cygwin: pty: Fixup pty state after a cygwin app exits
Previously, the cygwin process on pty is always a child of another
cygwin app on pty. If a cygwin app is a child of non-cygwin app
in pseudo console, it was running on console originating from
pseudo console. Now, the child of a non-cygwin app on pseudo console
is running on pty, so, it is necessary to restore the pty state
to the state where the parent process is running. This patch
does the following fixup when the cygwin process on pty exits:
1) Switch pipe mode from cyg-pipe to nat-pipe.
2) Notify the current cursor position to pseudo console
These prevent the problems:
1) Run 'cat' in cmd.exe and stop it by Ctrl-C. After that
cmd.exe cannot receive key input.
2) Run 'ps' in cmd.exe. The cursor position will not be
maintained correctly after that.
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Reviewed-by: Mark Geisert <mark@maxrnd.com>
This commit is contained in:
1 parent
ee929717bd
commit
b34394d456
3 files changed
+78
-4
No files matched your search
@@ -388,6 +388,52 @@ atexit_func (void)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_pty_slave::req_fixup_pcon_state (void)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
WaitForSingleObject (input_mutex, mutex_timeout);
|
||||
if (!get_ttyp ()->pcon_start_pid)
|
||||
break;
|
||||
/* Another request is on going. */
|
||||
ReleaseMutex (input_mutex);
|
||||
yield ();
|
||||
}
|
||||
|
||||
DWORD n;
|
||||
/* indicates that this "ESC[6n" is just for fixing-up cursor position */
|
||||
get_ttyp ()->req_fixup_pcon_cur_pos = true;
|
||||
get_ttyp ()->req_xfer_input = true; /* indicates that this "ESC[6n"
|
||||
is just for transfer input */
|
||||
get_ttyp ()->pcon_start = true;
|
||||
get_ttyp ()->pcon_start_pid = myself->pid;
|
||||
WriteFile (get_output_handle (), "\033[6n", 4, &n, NULL);
|
||||
ReleaseMutex (input_mutex);
|
||||
while (get_ttyp ()->pcon_start_pid)
|
||||
/* wait for completion of fixing-up in master::write(). */
|
||||
yield ();
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_pty_master::fixup_pcon_cursor_position (int x, int y)
|
||||
{
|
||||
HANDLE pcon_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
|
||||
get_ttyp ()->nat_pipe_owner_pid);
|
||||
HANDLE h_pcon_out = NULL;
|
||||
DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_out,
|
||||
GetCurrentProcess (), &h_pcon_out,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS);
|
||||
CloseHandle (pcon_owner);
|
||||
DWORD target_pid = get_ttyp ()->nat_pipe_owner_pid;
|
||||
DWORD resume_pid =
|
||||
fhandler_pty_common::attach_console_temporarily (target_pid);
|
||||
COORD cur_pos = {(SHORT) (x - 1), (SHORT) (y - 1)};
|
||||
SetConsoleCursorPosition (h_pcon_out, cur_pos);
|
||||
fhandler_pty_common::resume_from_temporarily_attach (resume_pid);
|
||||
CloseHandle (h_pcon_out);
|
||||
}
|
||||
|
||||
#define DEF_HOOK(name) static __typeof__ (name) *name##_Orig
|
||||
/* CreateProcess() is hooked for GDB etc. */
|
||||
DEF_HOOK (CreateProcessA);
|
||||
@@ -1162,6 +1208,19 @@ err_no_msg:
|
||||
bool
|
||||
fhandler_pty_slave::open_setup (int flags)
|
||||
{
|
||||
if (get_ttyp ()->pcon_activated)
|
||||
{
|
||||
HANDLE pcon_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
|
||||
get_ttyp ()->nat_pipe_owner_pid);
|
||||
DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_in,
|
||||
GetCurrentProcess (), &get_handle_nat (),
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS);
|
||||
DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_out,
|
||||
GetCurrentProcess (), &get_output_handle_nat (),
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS);
|
||||
CloseHandle (pcon_owner);
|
||||
}
|
||||
|
||||
set_flags ((flags & ~O_TEXT) | O_BINARY);
|
||||
myself->set_ctty (this, flags);
|
||||
report_tty_counts (this, "opened", "");
|
||||
@@ -1171,6 +1230,9 @@ fhandler_pty_slave::open_setup (int flags)
|
||||
void
|
||||
fhandler_pty_slave::cleanup ()
|
||||
{
|
||||
if (get_ttyp ()->pcon_activated && get_ttyp ()->getpgid () == myself->pgid)
|
||||
req_fixup_pcon_state ();
|
||||
|
||||
/* This used to always call fhandler_pty_common::close when we were execing
|
||||
but that caused multiple closes of the handles associated with this pty.
|
||||
Since close_all_files is not called until after the cygwin process has
|
||||
@@ -2488,10 +2550,21 @@ fhandler_pty_master::write (const void *ptr, size_t len)
|
||||
}
|
||||
if (state == 2)
|
||||
{
|
||||
/* req_xfer_input is true if "ESC[6n" was sent just for
|
||||
/* req_fixup_pcon_cur_pos is true if "ESC[6n" was sent
|
||||
for requesting cursor-position-fixup that is needed
|
||||
when a non-cygwin app executes a cygwin app and the
|
||||
cygwin app exits.
|
||||
req_xfer_input is true if "ESC[6n" was sent just for
|
||||
triggering transfer_input() in master. In this case,
|
||||
the response sequence should not be written. */
|
||||
if (!get_ttyp ()->req_xfer_input)
|
||||
if (get_ttyp ()->req_fixup_pcon_cur_pos)
|
||||
{
|
||||
int x, y;
|
||||
sscanf (wpbuf, "\033[%d;%dR", &y, &x);
|
||||
fixup_pcon_cursor_position (x, y);
|
||||
get_ttyp ()->req_fixup_pcon_cur_pos = false;
|
||||
}
|
||||
else if (!get_ttyp ()->req_xfer_input)
|
||||
WriteFile (to_slave_nat, wpbuf, ixput, &n, NULL);
|
||||
ixput = 0;
|
||||
state = 0;
|
||||
@@ -4113,8 +4186,6 @@ fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to)
|
||||
ttyp->pcon_activated = false;
|
||||
ttyp->switch_to_nat_pipe = false;
|
||||
ttyp->nat_pipe_owner_pid = 0;
|
||||
ttyp->pcon_start = false;
|
||||
ttyp->pcon_start_pid = 0;
|
||||
}
|
||||
if (ttyp->pcon_handle_ready_event)
|
||||
{
|
||||
|
||||
@@ -2533,6 +2533,7 @@ class fhandler_pty_slave: public fhandler_pty_common
|
||||
void setpgid_aux (pid_t pid);
|
||||
static void release_ownership_of_nat_pipe (tty *ttyp, fhandler_termios *fh);
|
||||
void replace_nat_handles (HANDLE new_input, HANDLE new_output);
|
||||
void req_fixup_pcon_state (void);
|
||||
};
|
||||
|
||||
#define __ptsname(buf, unit) __small_sprintf ((buf), "/dev/pty%d", (unit))
|
||||
@@ -2641,6 +2642,7 @@ public:
|
||||
void apply_line_edit_to_transferred_input ();
|
||||
line_edit_status line_edit_maybe (const char *p, size_t len, termios&,
|
||||
ssize_t *n);
|
||||
void fixup_pcon_cursor_position (int x, int y);
|
||||
};
|
||||
|
||||
class fhandler_dev_null: public fhandler_base
|
||||
|
||||
@@ -145,6 +145,7 @@ private:
|
||||
xfer_dir pty_input_state;
|
||||
bool discard_input;
|
||||
bool stop_fwd_thread;
|
||||
bool req_fixup_pcon_cur_pos;
|
||||
|
||||
public:
|
||||
HANDLE from_master_nat () const { return _from_master_nat; }
|
||||
|
||||
Reference in new issue
Block a user