From 71d59a926f9d632b15c531325bad15edb32b8f81 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Sat, 3 Jun 2006 20:32:07 +0000 Subject: [PATCH] * dcrt0.cc (dll_crt0_0): Call tty_list::init_session here. (dll_crt0_1): Reflect renaming from tty_init to tty::init_session. (do_exit): Reflect moving of tty_terminate into tty_list. * exceptions.cc (events_init): Move tty_mutex stuff elsewhere. * fhandler_console.cc (set_console_title): Use lock_ttys class. * fhandler_termios.cc (fhandler_termios::bg_check): Make debug output more accurate. * fhandler_tty.cc (fhandler_tty_slave::open): Reflect move of attach_tty into tty_list class. Don't attempt to grab master end of pty if master doesn't exist. (fhandler_pty_master::open): Reflect move of allocate_tty into tty_list class. Use lock_ttys::release to release mutex. Improve debugging output. (fhandler_pty_master::setup): Remove if 0'ed block. Fix argument to SetNamedPipeHandleState. * pinfo.cc (_pinfo::set_ctty): Lock ttys before setting sid/pgid. Improve debugging. Add temporary debugging. * tty.cc (tty_list::init_session): New function. (tty::init_session): Rename from tty_init. Reflect move of attach_tty to tty_list class. (tty::create_master): Rename from create_tty_master. (tty_list::attach): Rename from attach_tty. Reflect renaming of connect_tty to connect. Ditto for allocate_tty. (tty_terminate): Delete. (tty_list::terminate): Subsume tty_terminate. Use lock_ttys rather than manipulating mutex directly. (tty_list::allocate): Rename from allocate_tty. Use lock_ttys rather than manipulating mutex directly. Don't set sid here since linux apparently doesn't do this. Reflect move of create_tty_master into tty. (lock_ttys::lock_ttys): Define new constructor. (lock_ttys::release): New function. * tty.h (tty::exists): Return false immediately if !master_pid. (tty::set_master_closed): Define new function. (tty::create_master): Ditto. (tty::init_session): Ditto. (tty_list::mutex): New field. (tty_list::allocate): Define new function. (tty_list::connect): Ditto. (tty_list::attach): Ditto. (tty_list::init_session): Ditto. (lock_ttys): New class. (tty_init): Delete declaration. (tty_terminate): Ditto. (attach_tty): Ditto. (create_tty_master): Ditto. --- winsup/cygwin/ChangeLog | 49 ++++++++++++++++++++ winsup/cygwin/dcrt0.cc | 6 +-- winsup/cygwin/exceptions.cc | 17 +------ winsup/cygwin/fhandler_console.cc | 5 +-- winsup/cygwin/fhandler_termios.cc | 4 +- winsup/cygwin/fhandler_tty.cc | 33 ++++++++------ winsup/cygwin/pinfo.cc | 14 ++++-- winsup/cygwin/tty.cc | 75 ++++++++++++++++++------------- winsup/cygwin/tty.h | 31 ++++++++++--- 9 files changed, 157 insertions(+), 77 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f0ddfd65e..022ce7609 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,52 @@ +2006-06-03 Christopher Faylor + + * dcrt0.cc (dll_crt0_0): Call tty_list::init_session here. + (dll_crt0_1): Reflect renaming from tty_init to tty::init_session. + (do_exit): Reflect moving of tty_terminate into tty_list. + * exceptions.cc (events_init): Move tty_mutex stuff elsewhere. + * fhandler_console.cc (set_console_title): Use lock_ttys class. + * fhandler_termios.cc (fhandler_termios::bg_check): Make debug output + more accurate. + * fhandler_tty.cc (fhandler_tty_slave::open): Reflect move of + attach_tty into tty_list class. Don't attempt to grab master end of + pty if master doesn't exist. + (fhandler_pty_master::open): Reflect move of allocate_tty into tty_list + class. Use lock_ttys::release to release mutex. Improve debugging + output. + (fhandler_pty_master::setup): Remove if 0'ed block. Fix argument to + SetNamedPipeHandleState. + * pinfo.cc (_pinfo::set_ctty): Lock ttys before setting sid/pgid. + Improve debugging. Add temporary debugging. + * tty.cc (tty_list::init_session): New function. + (tty::init_session): Rename from tty_init. Reflect move of attach_tty + to tty_list class. + (tty::create_master): Rename from create_tty_master. + (tty_list::attach): Rename from attach_tty. Reflect renaming of + connect_tty to connect. Ditto for allocate_tty. + (tty_terminate): Delete. + (tty_list::terminate): Subsume tty_terminate. Use lock_ttys rather + than manipulating mutex directly. + (tty_list::allocate): Rename from allocate_tty. Use lock_ttys rather + than manipulating mutex directly. Don't set sid here since linux + apparently doesn't do this. Reflect move of create_tty_master into + tty. + (lock_ttys::lock_ttys): Define new constructor. + (lock_ttys::release): New function. + * tty.h (tty::exists): Return false immediately if !master_pid. + (tty::set_master_closed): Define new function. + (tty::create_master): Ditto. + (tty::init_session): Ditto. + (tty_list::mutex): New field. + (tty_list::allocate): Define new function. + (tty_list::connect): Ditto. + (tty_list::attach): Ditto. + (tty_list::init_session): Ditto. + (lock_ttys): New class. + (tty_init): Delete declaration. + (tty_terminate): Ditto. + (attach_tty): Ditto. + (create_tty_master): Ditto. + 2006-06-03 Christopher Faylor * Makefile.in (libdl.a): New library. diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 0228c3275..c3f4eace2 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -768,6 +768,7 @@ dll_crt0_0 () /* Initialize events */ events_init (); + tty_list::init_session (); cygheap->cwd.init (); @@ -867,9 +868,8 @@ dll_crt0_1 (void *) if (!threadfunc_ix) system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems."); - /* Connect to tty. */ - tty_init (); + tty::init_session (); if (!__argc) { @@ -1110,7 +1110,7 @@ do_exit (int status) if (exit_state < ES_TTY_TERMINATE) { exit_state = ES_TTY_TERMINATE; - tty_terminate (); + cygwin_shared->tty.terminate (); } myself.exit (n); diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index a5e71d86a..4d078dd10 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -369,7 +369,7 @@ try_to_debug (bool waitloop) /* if any of these mutexes is owned, we will fail to start any cygwin app until trapped app exits */ - ReleaseMutex (tty_mutex); + lock_ttys::release (); /* prevent recursive exception handling */ char* rawenv = GetEnvironmentStrings () ; @@ -1297,22 +1297,9 @@ _cygtls::signal_exit (int rc) do_exit (rc); } -HANDLE NO_COPY tty_mutex = NULL; - void events_init () { - char *name; - char mutex_name[CYG_MAX_PATH]; - /* tty_mutex is on while searching for a tty slot. It's necessary - while finding console window handle */ - - if (!(tty_mutex = CreateMutex (&sec_all_nih, FALSE, - name = shared_name (mutex_name, - "tty_mutex", 0)))) - api_fatal ("can't create title mutex '%s', %E", name); - - ProtectHandle (tty_mutex); mask_sync.init ("mask_sync"); windows_system_directory[0] = '\0'; GetSystemDirectory (windows_system_directory, sizeof (windows_system_directory) - 2); @@ -1393,7 +1380,7 @@ _cygtls::copy_context (CONTEXT *c) void _cygtls::signal_debugger (int sig) { - if (being_debugged ()) + if (isinitialized () && being_debugged ()) { char sigmsg[2 * sizeof (_CYGWIN_SIGNAL_STRING " ffffffff ffffffff")]; __small_sprintf (sigmsg, _CYGWIN_SIGNAL_STRING " %d %p %p", sig, thread_id, &thread_context); diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index 91a5e1549..7248e1747 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -1781,14 +1781,11 @@ fhandler_console::set_close_on_exec (bool val) void __stdcall set_console_title (char *title) { - int rc; char buf[257]; strncpy (buf, title, sizeof (buf) - 1); buf[sizeof (buf) - 1] = '\0'; - if ((rc = WaitForSingleObject (tty_mutex, 15000)) != WAIT_OBJECT_0) - sigproc_printf ("wait for title mutex failed rc %d, %E", rc); + lock_ttys here (15000); SetConsoleTitle (buf); - ReleaseMutex (tty_mutex); debug_printf ("title '%s'", buf); } diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc index bd0386cf4..0a6e05c00 100644 --- a/winsup/cygwin/fhandler_termios.cc +++ b/winsup/cygwin/fhandler_termios.cc @@ -138,8 +138,8 @@ fhandler_termios::bg_check (int sig) if (sig < 0) sig = -sig; - termios_printf ("bg I/O pgid %d, tpgid %d, %s", myself->pgid, tc->getpgid (), - myctty ()); + termios_printf ("bg I/O pgid %d, tpgid %d, %s, ntty tty%d", myself->pgid, tc->getpgid (), + myctty (), tc->ntty); if (tc->getsid () == 0) { diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index e006c4ced..b1d840acf 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -471,7 +471,7 @@ fhandler_tty_slave::open (int flags, mode_t) tcinit (cygwin_shared->tty[get_unit ()]); - attach_tty (get_unit ()); + cygwin_shared->tty.attach (get_unit ()); set_flags ((flags & ~O_TEXT) | O_BINARY); /* Create synchronisation events */ @@ -537,6 +537,12 @@ fhandler_tty_slave::open (int flags, mode_t) || !cygserver_attach_tty (&from_master_local, &to_master_local)) #endif { + if (get_ttyp ()->master_pid < 0) + { + set_errno (EAGAIN); + termios_printf ("*** master is closed"); + return 0; + } pinfo p (get_ttyp ()->master_pid); if (!p) { @@ -1087,7 +1093,8 @@ fhandler_pty_master::open (int flags, mode_t) goto out; } - int ntty = cygwin_shared->tty.allocate_tty (false); + int ntty; + ntty = cygwin_shared->tty.allocate (false); if (ntty < 0) return 0; @@ -1095,10 +1102,10 @@ fhandler_pty_master::open (int flags, mode_t) slave.setunit (ntty); if (!setup (*cygwin_shared->tty[ntty])) { - ReleaseMutex (tty_mutex); // lock was set in allocate_tty + lock_ttys::release (); return 0; } - ReleaseMutex (tty_mutex); // lock was set in allocate_tty + lock_ttys::release (); set_flags ((flags & ~O_TEXT) | O_BINARY); set_open_status (); // @@ -1112,8 +1119,9 @@ fhandler_pty_master::open (int flags, mode_t) out: usecount = 0; arch->usecount++; - report_tty_counts (this, "opened master", ""); - termios_printf ("opened pty master tty%d", get_unit ()); + char buf[sizeof ("opened pty master for ttyNNNNNNNNNNN")]; + __small_sprintf (buf, "opened pty master for tty%d", get_unit ()); + report_tty_counts (this, buf, ""); return 1; } @@ -1184,8 +1192,10 @@ fhandler_pty_master::close () } fhandler_tty_common::close (); - if (!hExeced && get_ttyp ()->master_pid == myself->pid) - get_ttyp ()->init (); + if (hExeced || get_ttyp ()->master_pid != myself->pid) + termios_printf ("not clearing: %d, master_pid %d", hExeced, get_ttyp ()->master_pid); + else + get_ttyp ()->set_master_closed (); return 0; } @@ -1337,11 +1347,6 @@ fhandler_pty_master::setup (tty& t) /* Create communication pipes */ -#if 0 // CGF: don't think this is needed since it is handled by the constructor - input_handle = io_handle = output_done_event = ioctl_done_event = - ioctl_request_event = input_available_event = output_mutex = input_mutex NULL; -#endif - /* FIXME: should this be sec_none_nih? */ if (!CreatePipe (&from_master, &get_output_handle (), &sec_all, 128 * 1024)) { @@ -1355,7 +1360,7 @@ fhandler_pty_master::setup (tty& t) goto err; } - if (!SetNamedPipeHandleState (&get_output_handle (), &pipe_mode, NULL, NULL)) + if (!SetNamedPipeHandleState (get_output_handle (), &pipe_mode, NULL, NULL)) termios_printf ("can't set output_handle(%p) to non-blocking mode", get_output_handle ()); diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 504c1c9f2..93ab9b945 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -331,14 +331,20 @@ _pinfo::set_ctty (tty_min *tc, int flags, fhandler_tty_slave *arch) if ((ctty < 0 || ctty == tc->ntty) && !(flags & O_NOCTTY)) { ctty = tc->ntty; - syscall_printf ("attached %s sid %d, pid %d, tty->pgid %d, tty->sid %d", - __ctty (), sid, pid, pgid, tc->getsid ()); + lock_ttys here; + syscall_printf ("attaching %s sid %d, pid %d, pgid %d, tty->pgid %d, tty->sid %d", + __ctty (), sid, pid, pgid, tc->getpgid (), tc->getsid ()); pinfo p (tc->getsid ()); if (sid == pid && (!p || p->pid == pid || !p->exists ())) { +#ifdef DEBUGGING + debug_printf ("resetting %s sid. Was %d, now %d. pgid was %d, now %d.", + __ctty (), tc->getsid (), sid, tc->getpgid (), pgid); +#else paranoid_printf ("resetting %s sid. Was %d, now %d. pgid was %d, now %d.", __ctty (), tc->getsid (), sid, tc->getpgid (), pgid); +#endif /* We are the session leader */ tc->setsid (sid); tc->setpgid (pgid); @@ -346,7 +352,9 @@ _pinfo::set_ctty (tty_min *tc, int flags, fhandler_tty_slave *arch) else sid = tc->getsid (); if (tc->getpgid () == 0) - tc->setpgid (pgid); +{debug_printf ("setting pgid to %d", pgid); + tc->setpgid (pgid); +} if (cygheap->ctty != arch) { debug_printf ("cygheap->ctty %p, arch %p", cygheap->ctty, arch); diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc index 69d6a9b34..018ffe08b 100644 --- a/winsup/cygwin/tty.cc +++ b/winsup/cygwin/tty.cc @@ -54,8 +54,23 @@ ttyslot (void) return myself->ctty; } +HANDLE NO_COPY tty_list::mutex = NULL; + void __stdcall -tty_init () +tty_list::init_session () +{ + char mutex_name[CYG_MAX_PATH]; + /* tty_list::mutex is used while searching for a tty slot. It's necessary + while finding console window handle */ + + char *name = shared_name (mutex_name, "tty_list::mutex", 0); + if (!(mutex = CreateMutex (&sec_all_nih, FALSE, name))) + api_fatal ("can't create tty_list::mutex '%s', %E", name); + ProtectHandle (mutex); +} + +void __stdcall +tty::init_session () { if (!myself->cygstarted && NOTSTATE (myself, PID_CYGPARENT)) cygheap->fdtab.get_debugger_info (); @@ -64,7 +79,7 @@ tty_init () return; if (myself->ctty == -1) if (NOTSTATE (myself, PID_CYGPARENT)) - myself->ctty = attach_tty (myself->ctty); + myself->ctty = cygwin_shared->tty.attach (myself->ctty); else return; if (myself->ctty == -1) @@ -74,7 +89,7 @@ tty_init () /* Create session's master tty */ void __stdcall -create_tty_master (int ttynum) +tty::create_master (int ttynum) { device ttym = *ttym_dev; ttym.setunit (ttynum); /* CGF FIXME device */ @@ -104,29 +119,23 @@ create_tty_master (int ttynum) } } -void __stdcall -tty_terminate () -{ - if (NOTSTATE (myself, PID_USETTY)) - return; - cygwin_shared->tty.terminate (); -} - int __stdcall -attach_tty (int num) +tty_list::attach (int num) { if (num != -1) { - return cygwin_shared->tty.connect_tty (num); + return connect (num); } if (NOTSTATE (myself, PID_USETTY)) return -1; - return cygwin_shared->tty.allocate_tty (true); + return allocate (true); } void tty_list::terminate () { + if (NOTSTATE (myself, PID_USETTY)) + return; int ttynum = myself->ctty; /* Keep master running till there are connected clients */ @@ -151,8 +160,7 @@ tty_list::terminate () low_priority_sleep (200); } - if (WaitForSingleObject (tty_mutex, INFINITE) == WAIT_FAILED) - termios_printf ("WFSO for tty_mutex %p failed, %E", tty_mutex); + lock_ttys here (); termios_printf ("tty %d master about to finish", ttynum); CloseHandle (tty_master->get_io_handle ()); @@ -163,13 +171,11 @@ tty_list::terminate () char buf[20]; __small_sprintf (buf, "tty%d", ttynum); logout (buf); - - ReleaseMutex (tty_mutex); } } int -tty_list::connect_tty (int ttynum) +tty_list::connect (int ttynum) { if (ttynum < 0 || ttynum >= NTTYS) { @@ -201,7 +207,7 @@ tty_list::init () If flag == 0, just find a free tty. */ int -tty_list::allocate_tty (bool with_console) +tty_list::allocate (bool with_console) { HWND console; int freetty = -1; @@ -209,8 +215,7 @@ tty_list::allocate_tty (bool with_console) /* FIXME: This whole function needs a protective mutex. */ - if (WaitForSingleObject (tty_mutex, INFINITE) == WAIT_FAILED) - termios_printf ("WFSO for tty_mutex %p failed, %E", tty_mutex); + lock_ttys here; if (!with_console) console = NULL; @@ -282,26 +287,21 @@ tty_list::allocate_tty (bool with_console) t = ttys + freetty; t->init (); t->setsid (-1); - t->setpgid (myself->pgid); t->sethwnd (console); out: if (freetty < 0) - { - ReleaseMutex (tty_mutex); - system_printf ("No tty allocated"); - } + system_printf ("No tty allocated"); else if (!with_console) { termios_printf ("tty%d allocated", freetty); - /* exit with tty_mutex still held -- caller has more work to do */ + here.dont_release (); /* exit with mutex still held -- caller has more work to do */ } else { termios_printf ("console %p associated with tty%d", console, freetty); if (!hmaster) - create_tty_master (freetty); - ReleaseMutex (tty_mutex); + tty::create_master (freetty); } return freetty; } @@ -386,3 +386,18 @@ tty::get_event (const char *fmt, BOOL manual_reset) termios_printf ("created event %s", buf); return hev; } + +lock_ttys::lock_ttys (DWORD howlong): release_me (true) +{ + if (WaitForSingleObject (tty_list::mutex, howlong) == WAIT_FAILED) + { + termios_printf ("WFSO for mutex %p failed, %E", tty_list::mutex); + release_me = false; + } +} + +void +lock_ttys::release () +{ + ReleaseMutex (tty_list::mutex); +} diff --git a/winsup/cygwin/tty.h b/winsup/cygwin/tty.h index ceb265e45..2343a93f6 100644 --- a/winsup/cygwin/tty.h +++ b/winsup/cygwin/tty.h @@ -105,6 +105,8 @@ public: HANDLE open_input_mutex (); bool exists () { + if (!master_pid) + return false; HANDLE h = open_output_mutex (); if (h) { @@ -113,24 +115,41 @@ public: } return slave_alive (); } + void set_master_closed () {master_pid = -1;} + static void __stdcall create_master (int); + static void __stdcall init_session (); friend class fhandler_pty_master; }; class tty_list { tty ttys[NTTYS]; + static HANDLE mutex; public: tty * operator [](int n) {return ttys + n;} - int allocate_tty (bool); /* true if allocate a tty, pty otherwise */ - int connect_tty (int); + int allocate (bool); /* true if allocate a tty, pty otherwise */ + int connect (int); void terminate (); void init (); tty_min *get_tty (int n); + int __stdcall attach (int); + static void __stdcall init_session (); + friend class lock_ttys; +}; + +class lock_ttys +{ + bool release_me; +public: + lock_ttys (DWORD = INFINITE); + static void release (); + void dont_release () {release_me = false;} + ~lock_ttys () + { + if (release_me) + release (); + } }; -void __stdcall tty_init (); -void __stdcall tty_terminate (); -int __stdcall attach_tty (int); -void __stdcall create_tty_master (int); extern "C" int ttyslot (void);