Skip to content

Commit bb42852

Browse files
tyan0github-cygwin
authored andcommitted
Cygwin: pty: Implement new pseudo console support.
- In this implementation, pseudo console is created for each native console app. Advantages and disadvantages of this implementation over the previous implementation are as follows. Advantages: 1) No performance degradation in pty output for cygwin process. https://cygwin.com/pipermail/cygwin/2020-February/243858.html 2) Free from the problem caused by difference of behaviour of control sequences between real terminal and pseudo console. https://cygwin.com/pipermail/cygwin/2019-December/243281.html https://cygwin.com/pipermail/cygwin/2020-February/243855.html 3) Free from the problem in cgdb and emacs gud. https://cygwin.com/pipermail/cygwin/2020-January/243601.html https://cygwin.com/pipermail/cygwin/2020-March/244146.html 4) Redrawing screen on executing native console apps is not necessary. 5) cygwin-console-helper is not necessary for the pseudo console support. 6) The codes for pseudo console support are much simpler than that of the previous one. Disadvantages: 1) The cygwin program which calls console API directly does not work. 2) The apps which use console API cannot be debugged with gdb. This is because pseudo console is not activated since gdb uses CreateProcess() rather than exec(). Even with this limitation, attaching gdb to native apps, in which pseudo console is already activated, works. 3) Typeahead key inputs are discarded while native console app is executed. Simirally, typeahead key inputs while cygwin app is executed are not inherited to native console app. 4) Code page cannot be changed by chcp.com. Acctually, chcp works itself and changes code page of its own pseudo console. However, since pseudo console is recreated for another process, it cannot inherit the code page. 5) system_printf() does not work after stderr is closed. (Same with cygwin 3.0.7) 6) Startup time of native console apps is about 3 times slower than previous implemenation. 7) Pseudo console cannot be activated if it is already activated for another process on same pty.
1 parent b9261fa commit bb42852

File tree

12 files changed

+349
-1729
lines changed

12 files changed

+349
-1729
lines changed

winsup/cygwin/dtable.cc

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -147,38 +147,6 @@ dtable::get_debugger_info ()
147147
void
148148
dtable::stdio_init ()
149149
{
150-
for (int i = 0; i < 3; i ++)
151-
{
152-
const int chk_order[] = {1, 0, 2};
153-
int fd = chk_order[i];
154-
fhandler_base *fh = cygheap->fdtab[fd];
155-
if (fh && fh->get_major () == DEV_PTYS_MAJOR)
156-
{
157-
fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
158-
if (ptys->get_pseudo_console ())
159-
{
160-
bool attached = !!fhandler_console::get_console_process_id
161-
(ptys->get_helper_process_id (), true);
162-
if (attached)
163-
break;
164-
else
165-
{
166-
/* Not attached to pseudo console in fork() or spawn()
167-
by some reason. This happens if the executable is
168-
a windows GUI binary, such as mintty. */
169-
FreeConsole ();
170-
if (AttachConsole (ptys->get_helper_process_id ()))
171-
{
172-
ptys->fixup_after_attach (false, fd);
173-
break;
174-
}
175-
}
176-
}
177-
}
178-
else if (fh && fh->get_major () == DEV_CONS_MAJOR)
179-
break;
180-
}
181-
182150
if (myself->cygstarted || ISSTATE (myself, PID_CYGPARENT))
183151
{
184152
tty_min *t = cygwin_shared->tty.get_cttyp ();

winsup/cygwin/fhandler.h

Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -326,16 +326,16 @@ class fhandler_base
326326
virtual size_t &raixput () { return ra.raixput; };
327327
virtual size_t &rabuflen () { return ra.rabuflen; };
328328

329-
virtual bool get_readahead_valid () { return raixget () < ralen (); }
329+
bool get_readahead_valid () { return raixget () < ralen (); }
330330
int puts_readahead (const char *s, size_t len = (size_t) -1);
331-
virtual int put_readahead (char value);
331+
int put_readahead (char value);
332332

333333
int get_readahead ();
334334
int peek_readahead (int queryput = 0);
335335

336336
void set_readahead_valid (int val, int ch = -1);
337337

338-
virtual int get_readahead_into_buffer (char *buf, size_t buflen);
338+
int get_readahead_into_buffer (char *buf, size_t buflen);
339339

340340
bool has_acls () const { return pc.has_acls (); }
341341

@@ -1905,7 +1905,7 @@ class fhandler_termios: public fhandler_base
19051905
int ioctl (int, void *);
19061906
tty_min *_tc;
19071907
tty *get_ttyp () {return (tty *) tc ();}
1908-
virtual int eat_readahead (int n);
1908+
int eat_readahead (int n);
19091909

19101910
public:
19111911
tty_min*& tc () {return _tc;}
@@ -2184,7 +2184,6 @@ class fhandler_console: public fhandler_termios
21842184
static bool need_invisible ();
21852185
static void free_console ();
21862186
static const char *get_nonascii_key (INPUT_RECORD& input_rec, char *);
2187-
static DWORD get_console_process_id (DWORD pid, bool match);
21882187

21892188
fhandler_console (void *) {}
21902189

@@ -2264,19 +2263,7 @@ class fhandler_pty_common: public fhandler_termios
22642263
return fh;
22652264
}
22662265

2267-
bool attach_pcon_in_fork (void)
2268-
{
2269-
return get_ttyp ()->attach_pcon_in_fork;
2270-
}
2271-
DWORD get_helper_process_id (void)
2272-
{
2273-
return get_ttyp ()->helper_process_id;
2274-
}
2275-
HPCON get_pseudo_console (void)
2276-
{
2277-
return get_ttyp ()->h_pseudo_console;
2278-
}
2279-
bool to_be_read_from_pcon (void);
2266+
void resize_pseudo_console (struct winsize *);
22802267

22812268
protected:
22822269
BOOL process_opost_output (HANDLE h,
@@ -2287,23 +2274,15 @@ class fhandler_pty_slave: public fhandler_pty_common
22872274
{
22882275
HANDLE inuse; // used to indicate that a tty is in use
22892276
HANDLE output_handle_cyg, io_handle_cyg;
2290-
DWORD pid_restore;
2291-
int fd;
22922277

22932278
/* Helper functions for fchmod and fchown. */
22942279
bool fch_open_handles (bool chown);
22952280
int fch_set_sd (security_descriptor &sd, bool chown);
22962281
void fch_close_handles ();
22972282

2298-
bool try_reattach_pcon ();
2299-
void restore_reattach_pcon ();
2300-
inline void free_attached_console ();
2301-
23022283
public:
23032284
/* Constructor */
23042285
fhandler_pty_slave (int);
2305-
/* Destructor */
2306-
~fhandler_pty_slave ();
23072286

23082287
void set_output_handle_cyg (HANDLE h) { output_handle_cyg = h; }
23092288
HANDLE& get_output_handle_cyg () { return output_handle_cyg; }
@@ -2315,9 +2294,6 @@ class fhandler_pty_slave: public fhandler_pty_common
23152294
ssize_t __stdcall write (const void *ptr, size_t len);
23162295
void __reg3 read (void *ptr, size_t& len);
23172296
int init (HANDLE, DWORD, mode_t);
2318-
int eat_readahead (int n);
2319-
int get_readahead_into_buffer (char *buf, size_t buflen);
2320-
bool get_readahead_valid (void);
23212297

23222298
int tcsetattr (int a, const struct termios *t);
23232299
int tcgetattr (struct termios *t);
@@ -2354,20 +2330,12 @@ class fhandler_pty_slave: public fhandler_pty_common
23542330
copyto (fh);
23552331
return fh;
23562332
}
2357-
void set_switch_to_pcon (int fd);
2333+
bool setup_pseudoconsole (STARTUPINFOEXW *si, bool nopcon);
2334+
void close_pseudoconsole (void);
2335+
void set_switch_to_pcon (void);
23582336
void reset_switch_to_pcon (void);
2359-
void push_to_pcon_screenbuffer (const char *ptr, size_t len, bool is_echo);
23602337
void mask_switch_to_pcon_in (bool mask);
2361-
void fixup_after_attach (bool native_maybe, int fd);
2362-
bool is_line_input (void)
2363-
{
2364-
return get_ttyp ()->ti.c_lflag & ICANON;
2365-
}
23662338
void setup_locale (void);
2367-
void set_freeconsole_on_close (bool val);
2368-
void trigger_redraw_screen (void);
2369-
void pull_pcon_input (void);
2370-
void update_pcon_input_state (bool need_lock);
23712339
};
23722340

23732341
#define __ptsname(buf, unit) __small_sprintf ((buf), "/dev/pty%d", (unit))
@@ -2392,7 +2360,6 @@ class fhandler_pty_master: public fhandler_pty_common
23922360
int process_slave_output (char *buf, size_t len, int pktmode_on);
23932361
void doecho (const void *str, DWORD len);
23942362
int accept_input ();
2395-
int put_readahead (char value);
23962363
int open (int flags, mode_t mode = 0);
23972364
void open_setup (int flags);
23982365
ssize_t __stdcall write (const void *ptr, size_t len);
@@ -2431,9 +2398,7 @@ class fhandler_pty_master: public fhandler_pty_common
24312398
copyto (fh);
24322399
return fh;
24332400
}
2434-
2435-
bool setup_pseudoconsole (void);
2436-
void transfer_input_to_pcon (void);
2401+
bool to_be_read_from_pcon (void);
24372402
};
24382403

24392404
class fhandler_dev_null: public fhandler_base

winsup/cygwin/fhandler_console.cc

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,18 +1206,6 @@ fhandler_console::close ()
12061206
if (con_ra.rabuf)
12071207
free (con_ra.rabuf);
12081208

1209-
/* If already attached to pseudo console, don't call free_console () */
1210-
cygheap_fdenum cfd (false);
1211-
while (cfd.next () >= 0)
1212-
if (cfd->get_major () == DEV_PTYM_MAJOR ||
1213-
cfd->get_major () == DEV_PTYS_MAJOR)
1214-
{
1215-
fhandler_pty_common *t =
1216-
(fhandler_pty_common *) (fhandler_base *) cfd;
1217-
if (get_console_process_id (t->get_helper_process_id (), true))
1218-
return 0;
1219-
}
1220-
12211209
if (!have_execed)
12221210
free_console ();
12231211
return 0;
@@ -3611,37 +3599,6 @@ fhandler_console::need_invisible ()
36113599
return b;
36123600
}
36133601

3614-
DWORD
3615-
fhandler_console::get_console_process_id (DWORD pid, bool match)
3616-
{
3617-
DWORD tmp;
3618-
DWORD num, num_req;
3619-
num = 1;
3620-
num_req = GetConsoleProcessList (&tmp, num);
3621-
DWORD *list;
3622-
while (true)
3623-
{
3624-
list = (DWORD *)
3625-
HeapAlloc (GetProcessHeap (), 0, num_req * sizeof (DWORD));
3626-
num = num_req;
3627-
num_req = GetConsoleProcessList (list, num);
3628-
if (num_req > num)
3629-
HeapFree (GetProcessHeap (), 0, list);
3630-
else
3631-
break;
3632-
}
3633-
num = num_req;
3634-
3635-
tmp = 0;
3636-
for (DWORD i=0; i<num; i++)
3637-
if ((match && list[i] == pid) || (!match && list[i] != pid))
3638-
/* Last one is the oldest. */
3639-
/* https://github.com/microsoft/terminal/issues/95 */
3640-
tmp = list[i];
3641-
HeapFree (GetProcessHeap (), 0, list);
3642-
return tmp;
3643-
}
3644-
36453602
DWORD
36463603
fhandler_console::__acquire_input_mutex (const char *fn, int ln, DWORD ms)
36473604
{

0 commit comments

Comments
 (0)