From 92ddb74290655b6f9394801dac4242c93e03f9ed Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Thu, 5 May 2011 22:30:53 +0000 Subject: [PATCH] * cygheap.cc (cygheap::close_ctty): Close ctty via close_with_arch(). * debug.cc (close_handle): Call debugger on failure. * devices.in (device::tty_to_real_device): Delete. * devices.h (device::tty_to_real_device): Ditto. * devices.cc: Regenerate. * dtable.cc: Delete old ifdef'ed vfork code. (dtable::release): Don't handle archetype here. (dtable::init_std_file_from_handle): Consolidate console tests. Generate major/minor for tty ASAP. Fix incorrect setting of DEV_TTYS* for serial. (fh_alloc): New function derived from build_fh_pc. Pass current tty when building tty. (build_pc_pc): Use fh_alloc to create. Set name from fh->dev if appropriate. Generate an archetype or point to one here. (dtable::dup_worker): Deal with archetypes. Rely on = operator copying whole class rather than just fhandler_base. (dtable::fixup_after_exec): Call close_with_arch to handle closing of fhandlers with archetypes. * fhandler.cc (fhandler_base::operator =): Call memcpy with fhandler's size() rather than sizeof fhandler_base. (fhandler_base::open_with_arch): New function. Handles opening of fhandler's with archetypes, dealing with usecounts, etc. (fhandler_base::close_with_arch): Ditto for close. * fhandler.h: Many changes for archetypes. (fhandler_base::set_name): Set both normalized path and regular path. (fhandler_base::open_with_arch): New function. (fhandler_base::open_setup): Ditto. (fhandler_base::use_archetype): Ditto. (fhandler_base::_archetype_usecount): Ditto. (fhandler_*::size): Ditto. (fhandler_dev_tape::open): Remove virtual decoration. (fhandler_console::use_archetype): New function. Return true. (fhandler_console::open_setup): New function. (fhandler_console::dup): Delete. (fhandler_tty_slave::fhandler_tty_slave): Redeclare to take an argument. (fhandler_tty_slave::use_archetype): New function. Return true. (fhandler_tty_slave::cleanup): New function. (fhandler_pty_master::use_archetype): New function. Return true. (fhandler_pty_master::cleanup): New function. (fhandler_pty_master::is_tty_master): New function. Return false. (fhandler_tty_master::is_tty_master): New function. Return true. (fhandler_dev_dsp::fhandler_dev_dsp): New function. Return true. (report_tty_counts): Only report on archetype's usecount if there is one. * fhandler_console.cc (fhandler_console::get_tty_stuff): Remove handling of setsid, set_ctty, set_flags, and manage_console_count. (fhandler_console::open_setup): New function. Implement functionality removed from get_tty_stuff. (fhandler_console::dup): Delete. (fhandler_console::output_tcsetattr): Set errno on error. (fhandler_console::fhandler_console): Set device early. (fhandler_console::init): Use open_with_arch to open console handles. (fhandler_console::fixup_after_fork_exec): Nuke most of the stuff for dealing with console handles. * fhandler_dsp.cc (fhandler_dev_dsp::open): Remove archetype handling. (fhandler_dev_dsp::write): Ditto. (fhandler_dev_dsp::read): Ditto. (fhandler_dev_dsp::close): Ditto. (fhandler_dev_dsp::dup): Ditto. (fhandler_dev_dsp::ioctl): Ditto. (fhandler_dev_dsp::fixup_after_fork): Ditto. (fhandler_dev_dsp::fixup_after_exec): Ditto. * fhandler_tty.cc (fhandler_tty_common::__acquire_output_mutex): Add a little more debugging. (fhandler_tty_common::__release_output_mutex): Ditto. (fhandler_pty_master::process_slave_output): Ditto. Don't do signal handling or pthread_cancel handling in the tty master thread. (process_output): Minor reorg. (fhandler_tty_slave::fhandler_tty_slave): Set device based on new ntty argument. (fhandler_tty_slave::open): Remove archetype handling. Move some processing into open_setup(). (fhandler_tty_slave::open_setup): New function. (fhandler_tty_slave::cleanup): New function. (fhandler_tty_slave::close): Remove archetype handling. Move some processing into cleanup(). (fhandler_tty_slave::init): Rename argument from f to h. Open device using open_with_arch(). Remove archetype handling. (fhandler_pty_master::dup): Ditto. (fhandler_pty_master::open): Ditto. (fhandler_pty_master::close): Ditto. Move some handling to cleanup(). (fhandler_pty_master::cleanup): New function. (fhandler_tty_master::init_console): Give unique name to captive console fhandler. * pinfo.cc (_pinfo::set_ctty): Rename argument from arch to fh. Eliminate archetype assumption. * syscalls.cc (close_all_files): Use close_with_arch for closing. (open): Use open_with_arch() rather than open(). (close): Use close_with_arch() rather than close(). --- winsup/cygwin/ChangeLog | 93 +++++++++++++++ winsup/cygwin/cygheap.cc | 6 +- winsup/cygwin/debug.cc | 5 +- winsup/cygwin/devices.cc | 9 -- winsup/cygwin/devices.h | 1 - winsup/cygwin/devices.in | 9 -- winsup/cygwin/dtable.cc | 170 +++++++-------------------- winsup/cygwin/fhandler.cc | 78 ++++++++++++- winsup/cygwin/fhandler.h | 79 +++++++++++-- winsup/cygwin/fhandler_console.cc | 50 +++----- winsup/cygwin/fhandler_dsp.cc | 50 +------- winsup/cygwin/fhandler_tty.cc | 186 +++++++++++------------------- winsup/cygwin/pinfo.cc | 47 ++++---- winsup/cygwin/syscalls.cc | 31 ++--- 14 files changed, 408 insertions(+), 406 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index df65b3bf5b..7ef8f01015 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,96 @@ +2011-05-05 Christopher Faylor + + * cygheap.cc (cygheap::close_ctty): Close ctty via close_with_arch(). + * debug.cc (close_handle): Call debugger on failure. + * devices.in (device::tty_to_real_device): Delete. + * devices.h (device::tty_to_real_device): Ditto. + * devices.cc: Regenerate. + * dtable.cc: Delete old ifdef'ed vfork code. + (dtable::release): Don't handle archetype here. + (dtable::init_std_file_from_handle): Consolidate console tests. + Generate major/minor for tty ASAP. Fix incorrect setting of DEV_TTYS* + for serial. + (fh_alloc): New function derived from build_fh_pc. Pass current tty + when building tty. + (build_pc_pc): Use fh_alloc to create. Set name from fh->dev if + appropriate. Generate an archetype or point to one here. + (dtable::dup_worker): Deal with archetypes. Rely on = operator copying + whole class rather than just fhandler_base. + (dtable::fixup_after_exec): Call close_with_arch to handle closing of + fhandlers with archetypes. + * fhandler.cc (fhandler_base::operator =): Call memcpy with fhandler's + size() rather than sizeof fhandler_base. + (fhandler_base::open_with_arch): New function. Handles opening of + fhandler's with archetypes, dealing with usecounts, etc. + (fhandler_base::close_with_arch): Ditto for close. + * fhandler.h: Many changes for archetypes. + (fhandler_base::set_name): Set both normalized path and regular path. + (fhandler_base::open_with_arch): New function. + (fhandler_base::open_setup): Ditto. + (fhandler_base::use_archetype): Ditto. + (fhandler_base::_archetype_usecount): Ditto. + (fhandler_*::size): Ditto. + (fhandler_dev_tape::open): Remove virtual decoration. + (fhandler_console::use_archetype): New function. Return true. + (fhandler_console::open_setup): New function. + (fhandler_console::dup): Delete. + (fhandler_tty_slave::fhandler_tty_slave): Redeclare to take an + argument. + (fhandler_tty_slave::use_archetype): New function. Return true. + (fhandler_tty_slave::cleanup): New function. + (fhandler_pty_master::use_archetype): New function. Return true. + (fhandler_pty_master::cleanup): New function. + (fhandler_pty_master::is_tty_master): New function. Return false. + (fhandler_tty_master::is_tty_master): New function. Return true. + (fhandler_dev_dsp::fhandler_dev_dsp): New function. Return true. + (report_tty_counts): Only report on archetype's usecount if there is + one. + * fhandler_console.cc (fhandler_console::get_tty_stuff): Remove + handling of setsid, set_ctty, set_flags, and manage_console_count. + (fhandler_console::open_setup): New function. Implement functionality + removed from get_tty_stuff. + (fhandler_console::dup): Delete. + (fhandler_console::output_tcsetattr): Set errno on error. + (fhandler_console::fhandler_console): Set device early. + (fhandler_console::init): Use open_with_arch to open console handles. + (fhandler_console::fixup_after_fork_exec): Nuke most of the stuff for + dealing with console handles. + * fhandler_dsp.cc (fhandler_dev_dsp::open): Remove archetype handling. + (fhandler_dev_dsp::write): Ditto. + (fhandler_dev_dsp::read): Ditto. + (fhandler_dev_dsp::close): Ditto. + (fhandler_dev_dsp::dup): Ditto. + (fhandler_dev_dsp::ioctl): Ditto. + (fhandler_dev_dsp::fixup_after_fork): Ditto. + (fhandler_dev_dsp::fixup_after_exec): Ditto. + * fhandler_tty.cc (fhandler_tty_common::__acquire_output_mutex): Add a + little more debugging. + (fhandler_tty_common::__release_output_mutex): Ditto. + (fhandler_pty_master::process_slave_output): Ditto. Don't do signal + handling or pthread_cancel handling in the tty master thread. + (process_output): Minor reorg. + (fhandler_tty_slave::fhandler_tty_slave): Set device based on new ntty + argument. + (fhandler_tty_slave::open): Remove archetype handling. Move some + processing into open_setup(). + (fhandler_tty_slave::open_setup): New function. + (fhandler_tty_slave::cleanup): New function. + (fhandler_tty_slave::close): Remove archetype handling. Move some + processing into cleanup(). + (fhandler_tty_slave::init): Rename argument from f to h. Open device + using open_with_arch(). Remove archetype handling. + (fhandler_pty_master::dup): Ditto. + (fhandler_pty_master::open): Ditto. + (fhandler_pty_master::close): Ditto. Move some handling to cleanup(). + (fhandler_pty_master::cleanup): New function. + (fhandler_tty_master::init_console): Give unique name to captive + console fhandler. + * pinfo.cc (_pinfo::set_ctty): Rename argument from arch to fh. + Eliminate archetype assumption. + * syscalls.cc (close_all_files): Use close_with_arch for closing. + (open): Use open_with_arch() rather than open(). + (close): Use close_with_arch() rather than close(). + 2011-05-05 Corinna Vinschen * pinfo.h (class push_process_state): New class to push a process state diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 8dde3dfe9c..8a2a1f4dc3 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -107,11 +107,7 @@ void init_cygheap::close_ctty () { debug_printf ("closing cygheap->ctty %p", cygheap->ctty); - /* FIXME: Support for console-as-ctty is limited due to the fact that - the console doesn't use archetypes - even though they could and should */ - if (cygheap->ctty->get_ttyp () - && cygheap->ctty->get_ttyp ()->ntty != TTY_CONSOLE) - cygheap->ctty->close (); + cygheap->ctty->close_with_arch (); cygheap->ctty = NULL; } diff --git a/winsup/cygwin/debug.cc b/winsup/cygwin/debug.cc index bea256cae5..3e2aa11451 100644 --- a/winsup/cygwin/debug.cc +++ b/winsup/cygwin/debug.cc @@ -226,7 +226,10 @@ close_handle (const char *func, int ln, HANDLE h, const char *name, bool force) ret = CloseHandle (h); if (!ret) - small_printf ("CloseHandle(%s<%p>) failed %s:%d, %E\n", name, h, func, ln); + { + system_printf ("CloseHandle(%s<%p>) failed %s:%d, %E", name, h, func, ln); + try_to_debug (); + } return ret; } #endif /*DEBUGGING*/ diff --git a/winsup/cygwin/devices.cc b/winsup/cygwin/devices.cc index 569d239e13..0bcaae0bc9 100644 --- a/winsup/cygwin/devices.cc +++ b/winsup/cygwin/devices.cc @@ -43439,15 +43439,6 @@ device::parse (_dev_t dev) parse (_major (dev), _minor (dev)); } -void -device::tty_to_real_device () -{ - if (!real_tty_attached (myself)) - *this = myself->ctty < 0 ? dev_bad_storage : *console_dev; - else - parse (DEV_TTYS_MAJOR, myself->ctty); -} - void device::parsedisk (int drive, int part) { diff --git a/winsup/cygwin/devices.h b/winsup/cygwin/devices.h index b4927f1ba7..5c9909a5f0 100644 --- a/winsup/cygwin/devices.h +++ b/winsup/cygwin/devices.h @@ -268,7 +268,6 @@ struct device return true; } static void init (); - void tty_to_real_device (); inline operator int () const {return devn;} inline void setfs (bool x) {dev_on_fs = x;} inline bool isfs () const {return dev_on_fs || devn == FH_FS;} diff --git a/winsup/cygwin/devices.in b/winsup/cygwin/devices.in index 7ce8994bbb..1b59d9493e 100644 --- a/winsup/cygwin/devices.in +++ b/winsup/cygwin/devices.in @@ -146,15 +146,6 @@ device::parse (_dev_t dev) parse (_major (dev), _minor (dev)); } -void -device::tty_to_real_device () -{ - if (!real_tty_attached (myself)) - *this = myself->ctty < 0 ? dev_bad_storage : *console_dev; - else - parse (DEV_TTYS_MAJOR, myself->ctty); -} - void device::parsedisk (int drive, int part) { diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index 5fbe0f4b90..654526065e 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -245,10 +245,7 @@ dtable::release (int fd) { if (fds[fd]->need_fixup_before ()) dec_need_fixup_before (); - fhandler_base *arch = fds[fd]->archetype; delete fds[fd]; - if (arch && !arch->usecount) - cygheap->fdtab.delete_archetype (arch); fds[fd] = NULL; } } @@ -309,25 +306,20 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle) else dev = *pipew_dev; } - else if (GetConsoleScreenBufferInfo (handle, &buf)) + else if (GetConsoleScreenBufferInfo (handle, &buf) + || GetNumberOfConsoleInputEvents (handle, (DWORD *) &buf)) { - /* Console output */ - if (ISSTATE (myself, PID_USETTY)) - dev.parse (FH_TTY); - else + /* Console I/O */ + if (!ISSTATE (myself, PID_USETTY)) dev = *console_dev; - } - else if (GetNumberOfConsoleInputEvents (handle, (DWORD *) &buf)) - { - /* Console input */ - if (ISSTATE (myself, PID_USETTY)) - dev.parse (FH_TTY); + else if (myself->ctty >= 0) + dev.parse (DEV_TTYS_MAJOR, myself->ctty); else - dev = *console_dev; + dev.parse (FH_TTY); } else if (GetCommState (handle, &dcb)) - /* serial */ - dev.parse (DEV_TTYS_MAJOR, 0); + /* FIXME: Not right - assumes ttyS0 */ + dev.parse (DEV_SERIAL_MAJOR, 0); else /* Try to figure it out from context - probably a disk file */ handle_to_fn (handle, name); @@ -434,15 +426,15 @@ build_fh_dev (const device& dev, const char *unix_name) } #define fh_unset ((fhandler_base *) 1) -fhandler_base * -build_fh_pc (path_conv& pc, bool set_name) +static fhandler_base * +fh_alloc (device dev) { fhandler_base *fh = fh_unset; - switch (pc.dev.major) + switch (dev.major) { case DEV_TTYS_MAJOR: - fh = cnew (fhandler_tty_slave) (); + fh = cnew (fhandler_tty_slave) (dev.minor); break; case DEV_TTYM_MAJOR: fh = cnew (fhandler_tty_master) (); @@ -469,7 +461,7 @@ build_fh_pc (path_conv& pc, bool set_name) fh = cnew (fhandler_serial) (); break; default: - switch (pc.dev) + switch (dev) { case FH_CONSOLE: case FH_CONIN: @@ -548,8 +540,8 @@ build_fh_pc (path_conv& pc, bool set_name) { if (myself->ctty == TTY_CONSOLE) fh = cnew (fhandler_console) (); - else if (myself->ctty >= 0) - fh = cnew (fhandler_tty_slave) (); + else + fh = cnew (fhandler_tty_slave) (myself->ctty); break; } case FH_KMSG: @@ -560,12 +552,34 @@ build_fh_pc (path_conv& pc, bool set_name) if (fh == fh_unset) fh = cnew (fhandler_nodevice) (); + return fh; +} + +fhandler_base * +build_fh_pc (path_conv& pc, bool set_name) +{ + fhandler_base *fh = fh_alloc (pc.dev); if (!fh) set_errno (EMFILE); + else if (fh->dev () != FH_BAD) + fh->set_name (fh->dev ().name); else if (set_name) fh->set_name (pc); + if (!fh->use_archetype ()) + /* doesn't use archetypes */; + else if ((fh->archetype = cygheap->fdtab.find_archetype (fh->dev ()))) + debug_printf ("found an archetype for %s(%d/%d)", fh->get_name (), fh->dev ().major, fh->dev ().minor); + else + { + debug_printf ("creating an archetype for %s(%d/%d)", fh->get_name (), fh->dev ().major, fh->dev ().minor); + fh->archetype = fh_alloc (fh->pc.dev); + *fh->archetype = *fh; + fh->archetype->archetype = NULL; + *cygheap->fdtab.add_archetype () = fh->archetype; + } + debug_printf ("fh %p", fh); return fh; } @@ -582,7 +596,8 @@ dtable::dup_worker (fhandler_base *oldfh, int flags) else { *newfh = *oldfh; - newfh->set_io_handle (NULL); + if (!oldfh->archetype) + newfh->set_io_handle (NULL); newfh->pc.reset_conv_handle (); if (oldfh->dup (newfh)) { @@ -592,11 +607,10 @@ dtable::dup_worker (fhandler_base *oldfh, int flags) } else { + newfh->usecount = 0; + newfh->archetype_usecount (1); /* The O_CLOEXEC flag enforces close-on-exec behaviour. */ - if (flags & O_CLOEXEC) - newfh->set_close_on_exec (true); - else - newfh->close_on_exec (false); + newfh->set_close_on_exec (!!(flags & O_CLOEXEC)); debug_printf ("duped '%s' old %p, new %p", oldfh->get_name (), oldfh->get_io_handle (), newfh->get_io_handle ()); } } @@ -754,7 +768,7 @@ dtable::fixup_after_exec () if (fh->archetype) { debug_printf ("closing fd %d since it is an archetype", i); - fh->close (); + fh->close_with_arch (); } release (i); } @@ -786,102 +800,6 @@ dtable::fixup_after_fork (HANDLE parent) } } -#ifdef NEWVFORK -int -dtable::vfork_child_dup () -{ - fhandler_base **newtable; - lock (); - newtable = (fhandler_base **) ccalloc (HEAP_ARGV, size, sizeof (fds[0])); - int res = 1; - - /* Remove impersonation */ - cygheap->user.deimpersonate (); - if (cygheap->ctty) - { - cygheap->ctty->usecount++; - cygheap->console_count++; - report_tty_counts (cygheap->ctty, "vfork dup", "incremented ", ""); - } - - for (size_t i = 0; i < size; i++) - if (not_open (i)) - continue; - else if ((newtable[i] = dup_worker (fds[i])) != NULL) - newtable[i]->set_close_on_exec (fds[i]->close_on_exec ()); - else - { - res = 0; - goto out; - } - - fds_on_hold = fds; - fds = newtable; - -out: - /* Restore impersonation */ - cygheap->user.reimpersonate (); - - unlock (); - return 1; -} - -void -dtable::vfork_parent_restore () -{ - lock (); - - fhandler_tty_slave *ctty_on_hold = cygheap->ctty_on_hold; - close_all_files (); - fhandler_base **deleteme = fds; - fds = fds_on_hold; - fds_on_hold = NULL; - cfree (deleteme); - unlock (); - - if (cygheap->ctty != ctty_on_hold) - { - cygheap->ctty = ctty_on_hold; // revert - cygheap->ctty->close (); // Undo previous bump of this archetype - } - cygheap->ctty_on_hold = NULL; -} - -void -dtable::vfork_child_fixup () -{ - if (!fds_on_hold) - return; - debug_printf ("here"); - fhandler_base **saveme = fds; - fds = fds_on_hold; - - fhandler_base *fh; - for (int i = 0; i < (int) size; i++) - if ((fh = fds[i]) != NULL) - { - fh->clear_readahead (); - if (!fh->archetype && fh->close_on_exec ()) - release (i); - else - { - fh->close (); - release (i); - } - } - - fds = saveme; - cfree (fds_on_hold); - fds_on_hold = NULL; - - if (cygheap->ctty_on_hold) - { - cygheap->ctty_on_hold->close (); - cygheap->ctty_on_hold = NULL; - } -} -#endif /*NEWVFORK*/ - static void decode_tty (char *buf, WCHAR *w32) { diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 9fad7ce4d8..304feed630 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -39,7 +39,7 @@ struct __cygwin_perfile *perfile_table; inline fhandler_base& fhandler_base::operator =(fhandler_base& x) { - memcpy (this, &x, sizeof *this); + memcpy (this, &x, size ()); pc = x.pc; rabuf = NULL; ralen = 0; @@ -449,6 +449,40 @@ fhandler_base::fhaccess (int flags, bool effective) return res; } +int +fhandler_base::open_with_arch (int flags, mode_t mode) +{ + int res; + close_on_exec (flags & O_CLOEXEC); + if (!(res = (archetype && archetype->io_handle) + || open (flags, (mode & 07777) & ~cygheap->umask))) + { + if (archetype) + delete archetype; + } + else if (archetype) + { + if (!archetype->io_handle) + { + usecount = 0; + *archetype = *this; + archetype_usecount (1); + archetype->archetype = NULL; + } + else + { + fhandler_base *arch = archetype; + *this = *archetype; + archetype = arch; + archetype_usecount (1); + usecount = 0; + } + open_setup (flags); + } + + return res; +} + /* Open system call handler function. */ int fhandler_base::open (int flags, mode_t mode) @@ -1029,6 +1063,48 @@ fhandler_base::pwrite (void *, size_t, _off64_t) return -1; } +int +fhandler_base::close_with_arch () +{ + int res; + fhandler_base *fh; + if (usecount) + { + if (!--usecount) + debug_printf ("closing passed in archetype, usecount %d", usecount); + else + { + debug_printf ("not closing passed in archetype, usecount %d", usecount); + return 0; + } + fh = this; + } + else if (!archetype) + fh = this; + else + { + cleanup (); + if (archetype_usecount (-1) == 0) + { + debug_printf ("closing archetype"); + fh = archetype; + } + else + { + debug_printf ("not closing archetype"); + return 0; + } + } + + res = fh->close (); + if (archetype) + { + cygheap->fdtab.delete_archetype (archetype); + archetype = NULL; + } + return res; +} + int fhandler_base::close () { diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 14922b8b9f..6ceaff33ab 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -178,8 +178,13 @@ class fhandler_base path_conv pc; + virtual bool use_archetype () const {return false;} virtual void set_name (path_conv &pc); - virtual void set_name (const char *s) {pc.set_normalized_path (s);} + virtual void set_name (const char *s) + { + pc.set_normalized_path (s); + pc.set_path (s); + } int error () const {return pc.error;} void set_error (int error) {pc.error = error;} bool exists () const {return pc.exists ();} @@ -290,9 +295,24 @@ class fhandler_base bool fork_fixup (HANDLE, HANDLE &, const char *); virtual bool need_fixup_before () const {return false;} - virtual int open (int, mode_t = 0); + int open_with_arch (int, mode_t = 0); + virtual int open (int, mode_t); + virtual void open_setup (int flags) { return; } + int open_fs (int, mode_t = 0); + virtual int close_with_arch (); virtual int close (); + virtual void cleanup () { return; } + int _archetype_usecount (const char *fn, int ln, int n) + { + if (!archetype) + return 0; + archetype->usecount += n; + if (strace.active ()) + strace.prntf (_STRACE_ALL, fn, "line %d: %s<%p> usecount + %d = %d", ln, get_name (), archetype, n, archetype->usecount); + return archetype->usecount; + } +# define archetype_usecount(n) _archetype_usecount (__PRETTY_FUNCTION__, __LINE__, (n)) int close_fs () { return fhandler_base::close (); } virtual int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fstat_fs (struct __stat64 *buf) __attribute__ ((regparm (2))); @@ -548,6 +568,7 @@ class fhandler_socket: public fhandler_base int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2))); int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3))); int __stdcall link (const char *) __attribute__ ((regparm (2))); + size_t size () const { return sizeof (*this);} }; class fhandler_base_overlapped: public fhandler_base @@ -612,6 +633,7 @@ class fhandler_pipe: public fhandler_base_overlapped static int create (fhandler_pipe *[2], unsigned, int); static int create_selectable (LPSECURITY_ATTRIBUTES, HANDLE&, HANDLE&, DWORD, const char * = NULL); friend class fhandler_fifo; + size_t size () const { return sizeof (*this);} }; class fhandler_fifo: public fhandler_base_overlapped @@ -645,6 +667,7 @@ class fhandler_fifo: public fhandler_base_overlapped select_record *select_read (select_stuff *); select_record *select_write (select_stuff *); select_record *select_except (select_stuff *); + size_t size () const { return sizeof (*this);} }; class fhandler_mailslot : public fhandler_base_overlapped @@ -657,6 +680,7 @@ class fhandler_mailslot : public fhandler_base_overlapped ssize_t __stdcall raw_write (const void *, size_t) __attribute__ ((regparm (3))); int ioctl (unsigned int cmd, void *); select_record *select_read (select_stuff *); + size_t size () const { return sizeof (*this);} }; class fhandler_dev_raw: public fhandler_base @@ -689,6 +713,7 @@ class fhandler_dev_raw: public fhandler_base void fixup_after_fork (HANDLE); void fixup_after_exec (); + size_t size () const { return sizeof (*this);} }; #define MAX_PARTITIONS 15 @@ -732,6 +757,7 @@ class fhandler_dev_floppy: public fhandler_dev_raw ssize_t __stdcall raw_write (const void *ptr, size_t ulen) __attribute__ ((regparm (3))); _off64_t lseek (_off64_t offset, int whence); int ioctl (unsigned int cmd, void *buf); + size_t size () const { return sizeof (*this);} }; class fhandler_dev_tape: public fhandler_dev_raw @@ -749,7 +775,7 @@ class fhandler_dev_tape: public fhandler_dev_raw public: fhandler_dev_tape (); - virtual int open (int flags, mode_t mode = 0); + int open (int flags, mode_t mode = 0); virtual int close (); void __stdcall raw_read (void *ptr, size_t& ulen) __attribute__ ((regparm (3))); @@ -763,6 +789,7 @@ class fhandler_dev_tape: public fhandler_dev_raw virtual void fixup_after_fork (HANDLE parent); virtual void set_close_on_exec (bool val); virtual int ioctl (unsigned int cmd, void *buf); + size_t size () const { return sizeof (*this);} }; /* Standard disk file */ @@ -806,6 +833,7 @@ class fhandler_disk_file: public fhandler_base ssize_t __stdcall pread (void *, size_t, _off64_t) __attribute__ ((regparm (3))); ssize_t __stdcall pwrite (void *, size_t, _off64_t) __attribute__ ((regparm (3))); + size_t size () const { return sizeof (*this);} }; class fhandler_cygdrive: public fhandler_disk_file @@ -827,6 +855,7 @@ class fhandler_cygdrive: public fhandler_disk_file void rewinddir (DIR *); int closedir (DIR *); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); + size_t size () const { return sizeof (*this);} }; class fhandler_serial: public fhandler_base @@ -875,6 +904,7 @@ class fhandler_serial: public fhandler_base select_record *select_write (select_stuff *); select_record *select_except (select_stuff *); bool is_slow () {return true;} + size_t size () const { return sizeof (*this);} }; #define acquire_output_mutex(ms) \ @@ -1048,7 +1078,10 @@ class fhandler_console: public fhandler_termios fhandler_console* is_console () { return this; } - int open (int flags, mode_t mode = 0); + bool use_archetype () const {return true;} + + int open (int flags, mode_t mode); + void open_setup (int flags); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); ssize_t __stdcall write (const void *ptr, size_t len); @@ -1059,9 +1092,6 @@ class fhandler_console: public fhandler_termios int tcsetattr (int a, const struct termios *t); int tcgetattr (struct termios *t); - /* Special dup as we must dup two handles */ - int dup (fhandler_base *child); - int ioctl (unsigned int cmd, void *); int init (HANDLE, DWORD, mode_t); bool mouse_aware (MOUSE_EVENT_RECORD& mouse_event); @@ -1080,6 +1110,7 @@ class fhandler_console: public fhandler_termios bool is_slow () {return true;} static bool need_invisible (); static bool has_a () {return !invisible_console;} + size_t size () const { return sizeof (*this);} }; class fhandler_tty_common: public fhandler_termios @@ -1124,9 +1155,11 @@ class fhandler_tty_slave: public fhandler_tty_common public: /* Constructor */ - fhandler_tty_slave (); + fhandler_tty_slave (int); + bool use_archetype () const {return true;} int open (int flags, mode_t mode = 0); + void open_setup (int flags); ssize_t __stdcall write (const void *ptr, size_t len); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); int init (HANDLE, DWORD, mode_t); @@ -1136,6 +1169,7 @@ class fhandler_tty_slave: public fhandler_tty_common int tcflush (int); int ioctl (unsigned int cmd, void *); int close (); + void cleanup (); int dup (fhandler_base *child); void fixup_after_fork (HANDLE parent); void fixup_after_exec (); @@ -1146,6 +1180,7 @@ class fhandler_tty_slave: public fhandler_tty_common int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1))); int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2))); + size_t size () const { return sizeof (*this);} }; class fhandler_pty_master: public fhandler_tty_common @@ -1161,6 +1196,7 @@ class fhandler_pty_master: public fhandler_tty_common /* Constructor */ fhandler_pty_master (); + virtual bool use_archetype () const {return true;} DWORD pty_master_thread (); int process_slave_output (char *buf, size_t len, int pktmode_on); void doecho (const void *str, DWORD len); @@ -1169,6 +1205,7 @@ class fhandler_pty_master: public fhandler_tty_common ssize_t __stdcall write (const void *ptr, size_t len); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); int close (); + void cleanup (); int tcsetattr (int a, const struct termios *t); int tcgetattr (struct termios *t); @@ -1184,6 +1221,8 @@ class fhandler_pty_master: public fhandler_tty_common void fixup_after_fork (HANDLE parent); void fixup_after_exec (); int tcgetpgrp (); + virtual bool is_tty_master () const {return false;} + size_t size () const { return sizeof (*this);} }; class fhandler_tty_master: public fhandler_pty_master @@ -1191,11 +1230,14 @@ class fhandler_tty_master: public fhandler_pty_master public: /* Constructor */ fhandler_console *console; // device handler to perform real i/o. + bool use_archetype () const {return false;} fhandler_tty_master (); int init (); int init_console (); void set_winsize (bool); + bool is_tty_master () const {return true;} + size_t size () const { return sizeof (*this);} }; class fhandler_dev_null: public fhandler_base @@ -1206,6 +1248,7 @@ class fhandler_dev_null: public fhandler_base select_record *select_read (select_stuff *); select_record *select_write (select_stuff *); select_record *select_except (select_stuff *); + size_t size () const { return sizeof (*this);} }; class fhandler_dev_zero: public fhandler_base @@ -1224,6 +1267,7 @@ class fhandler_dev_zero: public fhandler_base virtual bool fixup_mmap_after_fork (HANDLE h, int prot, int flags, _off64_t offset, DWORD size, void *address); + size_t size () const { return sizeof (*this);} }; class fhandler_dev_random: public fhandler_base @@ -1245,6 +1289,7 @@ class fhandler_dev_random: public fhandler_base _off64_t lseek (_off64_t offset, int whence); int close (); int dup (fhandler_base *child); + size_t size () const { return sizeof (*this);} }; class fhandler_dev_mem: public fhandler_base @@ -1269,7 +1314,8 @@ class fhandler_dev_mem: public fhandler_base int msync (HANDLE h, caddr_t addr, size_t len, int flags); bool fixup_mmap_after_fork (HANDLE h, int prot, int flags, _off64_t offset, DWORD size, void *address); -} ; + size_t size () const { return sizeof (*this);} +}; class fhandler_dev_clipboard: public fhandler_base { @@ -1288,6 +1334,7 @@ class fhandler_dev_clipboard: public fhandler_base int dup (fhandler_base *child); void fixup_after_exec (); + size_t size () const { return sizeof (*this);} }; class fhandler_windows: public fhandler_base @@ -1310,6 +1357,7 @@ class fhandler_windows: public fhandler_base select_record *select_read (select_stuff *); select_record *select_write (select_stuff *); select_record *select_except (select_stuff *); + size_t size () const { return sizeof (*this);} }; class fhandler_dev_dsp: public fhandler_base @@ -1334,12 +1382,13 @@ class fhandler_dev_dsp: public fhandler_base int ioctl (unsigned int cmd, void *); _off64_t lseek (_off64_t, int); int close (); - int dup (fhandler_base *child); void fixup_after_fork (HANDLE parent); void fixup_after_exec (); private: void close_audio_in (); void close_audio_out (bool immediately = false); + size_t size () const { return sizeof (*this);} + bool use_archetype () const {return true;} }; class fhandler_virtual : public fhandler_base @@ -1374,6 +1423,7 @@ class fhandler_virtual : public fhandler_base virtual bool fill_filebuf (); char *get_filebuf () { return filebuf; } void fixup_after_exec (); + virtual size_t size () const { return sizeof (*this);} }; class fhandler_proc: public fhandler_virtual @@ -1387,6 +1437,7 @@ class fhandler_proc: public fhandler_virtual int open (int flags, mode_t mode = 0); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); bool fill_filebuf (); + virtual size_t size () const { return sizeof (*this);} }; class fhandler_procsys: public fhandler_virtual @@ -1406,6 +1457,7 @@ class fhandler_procsys: public fhandler_virtual ssize_t __stdcall write (const void *ptr, size_t len); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); bool fill_filebuf (); + size_t size () const { return sizeof (*this);} }; class fhandler_procsysvipc: public fhandler_proc @@ -1418,6 +1470,7 @@ class fhandler_procsysvipc: public fhandler_proc int open (int flags, mode_t mode = 0); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); bool fill_filebuf (); + size_t size () const { return sizeof (*this);} }; class fhandler_netdrive: public fhandler_virtual @@ -1431,6 +1484,7 @@ class fhandler_netdrive: public fhandler_virtual int closedir (DIR *); int open (int flags, mode_t mode = 0); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); + size_t size () const { return sizeof (*this);} }; class fhandler_registry: public fhandler_proc @@ -1454,6 +1508,7 @@ class fhandler_registry: public fhandler_proc bool fill_filebuf (); int close (); int dup (fhandler_base *child); + size_t size () const { return sizeof (*this);} }; class pinfo; @@ -1468,6 +1523,7 @@ class fhandler_process: public fhandler_proc int open (int flags, mode_t mode = 0); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); bool fill_filebuf (); + size_t size () const { return sizeof (*this);} }; class fhandler_procnet: public fhandler_proc @@ -1480,6 +1536,7 @@ class fhandler_procnet: public fhandler_proc int open (int flags, mode_t mode = 0); int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); bool fill_filebuf (); + size_t size () const { return sizeof (*this);} }; struct fhandler_nodevice: public fhandler_base @@ -1492,7 +1549,7 @@ struct fhandler_nodevice: public fhandler_base #define report_tty_counts(fh, call, use_op) \ termios_printf ("%s %s, %susecount %d",\ fh->ttyname (), call,\ - use_op, ((fhandler_tty_slave *) fh)->archetype->usecount); + use_op, ((fhandler_tty_slave *) (fh->archetype ?: fh))->usecount); typedef union { diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index b33b14deea..8fe4414cc1 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -94,8 +94,6 @@ fhandler_console::get_tty_stuff (int flags = 0) if (!shared_console_info->tty_min_state.ntty) { shared_console_info->tty_min_state.setntty (TTY_CONSOLE); - shared_console_info->tty_min_state.setsid (myself->sid); - myself->set_ctty (&shared_console_info->tty_min_state, flags, this); dev_state->scroll_region.Bottom = -1; dev_state->dwLastCursorPosition.X = -1; @@ -700,8 +698,6 @@ fhandler_console::open (int flags, mode_t) set_io_handle (NULL); set_output_handle (NULL); - set_flags ((flags & ~O_TEXT) | O_BINARY); - /* Open the input handle as handle_ */ h = CreateFile ("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, sec_none_cloexec (flags), @@ -735,7 +731,6 @@ fhandler_console::open (int flags, mode_t) tc->rstcons (false); set_open_status (); - cygheap->manage_console_count ("fhandler_console::open", 1); DWORD cflags; if (GetConsoleMode (get_io_handle (), &cflags)) @@ -748,6 +743,14 @@ fhandler_console::open (int flags, mode_t) return 1; } +void +fhandler_console::open_setup (int flags) +{ + cygheap->manage_console_count ("fhandler_console::open", 1); + set_flags ((flags & ~O_TEXT) | O_BINARY); + myself->set_ctty (&shared_console_info->tty_min_state, flags, this); +} + int fhandler_console::close () { @@ -758,19 +761,6 @@ fhandler_console::close () return 0; } -/* Special console dup to duplicate input and output handles. */ - -int -fhandler_console::dup (fhandler_base *child) -{ - fhandler_console *fhc = (fhandler_console *) child; - - if (!fhc->open (get_flags () & ~O_NOCTTY, 0)) - system_printf ("error opening console, %E"); - - return 0; -} - int fhandler_console::ioctl (unsigned int cmd, void *buf) { @@ -855,6 +845,8 @@ fhandler_console::output_tcsetattr (int, struct termios const *t) DWORD flags = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; int res = SetConsoleMode (get_output_handle (), flags) ? 0 : -1; + if (!res) + __seterrno_from_win_error (GetLastError ()); syscall_printf ("%d = tcsetattr (,%x) (ENABLE FLAGS %x) (lflag %x oflag %x)", res, t, flags, t->c_lflag, t->c_oflag); return res; @@ -980,6 +972,7 @@ fhandler_console::tcgetattr (struct termios *t) fhandler_console::fhandler_console () : fhandler_termios () { + dev ().parse (FH_CONSOLE); trunc_buf.len = 0; } @@ -2094,7 +2087,7 @@ fhandler_console::init (HANDLE h, DWORD a, mode_t bin) flags = O_WRONLY; if (a == (GENERIC_READ | GENERIC_WRITE)) flags = O_RDWR; - open (flags | O_BINARY | (h ? 0 : O_NOCTTY)); + open_with_arch (flags | O_BINARY | (h ? 0 : O_NOCTTY)); if (h && h != INVALID_HANDLE_VALUE) CloseHandle (h); /* Reopened by open */ @@ -2127,24 +2120,7 @@ set_console_title (char *title) void fhandler_console::fixup_after_fork_exec (bool execing) { - HANDLE h = get_handle (); - HANDLE oh = get_output_handle (); - - if ((execing && close_on_exec ()) || open (O_NOCTTY | get_flags (), 0)) - cygheap->manage_console_count ("fhandler_console::fixup_after_fork_exec", -1); - else - { - if (!get_io_handle ()) - system_printf ("error opening input console handle for %s after fork/exec, errno %d, %E", get_name (), get_errno ()); - if (!get_output_handle ()) - system_printf ("error opening output console handle for %s after fork/exec, errno %d, %E", get_name (), get_errno ()); - } - - if (!close_on_exec ()) - { - CloseHandle (h); - CloseHandle (oh); - } + get_tty_stuff (); } bool NO_COPY fhandler_console::invisible_console; diff --git a/winsup/cygwin/fhandler_dsp.cc b/winsup/cygwin/fhandler_dsp.cc index f784ca358c..488cd864e6 100644 --- a/winsup/cygwin/fhandler_dsp.cc +++ b/winsup/cygwin/fhandler_dsp.cc @@ -1006,11 +1006,6 @@ fhandler_dev_dsp::fhandler_dev_dsp (): int fhandler_dev_dsp::open (int flags, mode_t mode) { - if (cygheap->fdtab.find_archetype (dev ())) - { - set_errno (EBUSY); - return 0; - } int err = 0; UINT num_in = 0, num_out = 0; set_flags ((flags & ~O_TEXT) | O_BINARY); @@ -1042,13 +1037,6 @@ fhandler_dev_dsp::open (int flags, mode_t mode) set_open_status (); need_fork_fixup (true); nohandle (true); - - // FIXME: Do this better someday - fhandler_dev_dsp *arch = (fhandler_dev_dsp *) cmalloc_abort (HEAP_ARCHETYPES, sizeof (*this)); - archetype = arch; - *((fhandler_dev_dsp **) cygheap->fdtab.add_archetype ()) = arch; - *arch = *this; - archetype->usecount = 1; } else set_errno (err); @@ -1065,9 +1053,6 @@ ssize_t __stdcall fhandler_dev_dsp::write (const void *ptr, size_t len) { debug_printf ("ptr=%08x len=%d", ptr, len); - if ((fhandler_dev_dsp *) archetype != this) - return ((fhandler_dev_dsp *)archetype)->write(ptr, len); - int len_s = len; const char *ptr_s = static_cast (ptr); @@ -1114,8 +1099,6 @@ void __stdcall fhandler_dev_dsp::read (void *ptr, size_t& len) { debug_printf ("ptr=%08x len=%d", ptr, len); - if ((fhandler_dev_dsp *) archetype != this) - return ((fhandler_dev_dsp *)archetype)->read(ptr, len); if (audio_in_) /* nothing to do */; @@ -1181,27 +1164,8 @@ fhandler_dev_dsp::close () { debug_printf ("audio_in=%08x audio_out=%08x", (int)audio_in_, (int)audio_out_); - if (!hExeced) - { - if ((fhandler_dev_dsp *) archetype != this) - return ((fhandler_dev_dsp *) archetype)->close (); - - if (--usecount == 0) - { - close_audio_in (); - close_audio_out (exit_state != ES_NOT_EXITING); - } - } - return 0; -} - -int -fhandler_dev_dsp::dup (fhandler_base * child) -{ - debug_printf (""); - child->archetype = archetype; - child->set_flags (get_flags ()); - archetype->usecount++; + close_audio_in (); + close_audio_out (exit_state != ES_NOT_EXITING); return 0; } @@ -1210,9 +1174,6 @@ fhandler_dev_dsp::ioctl (unsigned int cmd, void *ptr) { debug_printf ("audio_in=%08x audio_out=%08x", (int)audio_in_, (int)audio_out_); - if ((fhandler_dev_dsp *) archetype != this) - return ((fhandler_dev_dsp *)archetype)->ioctl(cmd, ptr); - int *intptr = (int *) ptr; switch (cmd) { @@ -1419,11 +1380,9 @@ fhandler_dev_dsp::fixup_after_fork (HANDLE parent) { // called from new child process debug_printf ("audio_in=%08x audio_out=%08x", (int)audio_in_, (int)audio_out_); - if (archetype != this) - return ((fhandler_dev_dsp *)archetype)->fixup_after_fork (parent); if (audio_in_) - audio_in_ ->fork_fixup (parent); + audio_in_->fork_fixup (parent); if (audio_out_) audio_out_->fork_fixup (parent); } @@ -1435,9 +1394,6 @@ fhandler_dev_dsp::fixup_after_exec () (int) audio_in_, (int) audio_out_, close_on_exec ()); if (!close_on_exec ()) { - if (archetype != this) - return ((fhandler_dev_dsp *) archetype)->fixup_after_exec (); - audio_in_ = NULL; audio_out_ = NULL; } diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index f55eab21e3..42e5391913 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -113,7 +113,7 @@ fhandler_tty_common::__acquire_output_mutex (const char *fn, int ln, DWORD ms) { if (strace.active ()) - strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex: waiting %d ms", ln, ms); + strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex (%p): waiting %d ms", ln, output_mutex, ms); DWORD res = WaitForSingleObject (output_mutex, ms); if (res == WAIT_OBJECT_0) { @@ -138,11 +138,11 @@ fhandler_tty_common::__release_output_mutex (const char *fn, int ln) { #ifndef DEBUGGING if (strace.active ()) - strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex released", ln); + strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex(%p) released", ln, output_mutex); #else if (osi > 0) osi--; - termios_printf ("released at %s:%d, osi %d", fn, ln, osi); + termios_printf ("released(%p) at %s:%d, osi %d", output_mutex, fn, ln, osi); termios_printf (" for %s:%d (%s)", ostack[osi].fn, ostack[osi].ln, ostack[osi].tname); ostack[osi].ln = -ln; #endif @@ -299,7 +299,10 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on while (1) { if (!PeekNamedPipe (handle, NULL, 0, NULL, &n, NULL)) - goto err; + { + termios_printf ("PeekNamedPipe failed, %E"); + goto err; + } if (n > 0) break; if (hit_eof ()) @@ -307,6 +310,10 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on /* DISCARD (FLUSHO) and tcflush can finish here. */ if ((get_ttyp ()->ti.c_lflag & FLUSHO || !buf)) goto out; + + if (is_tty_master ()) + continue; + if (is_nonblocking ()) { set_errno (EAGAIN); @@ -321,17 +328,19 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on rc = -1; goto out; } - } - if (ReadFile (handle, outbuf, rlen, &n, NULL) == FALSE) - goto err; + if (!ReadFile (handle, outbuf, rlen, &n, NULL)) + { + termios_printf ("ReadFile failed, %E"); + goto err; + } } termios_printf ("bytes read %u", n); get_ttyp ()->write_error = 0; if (output_done_event != NULL) - SetEvent (output_done_event); + SetEvent (output_done_event); if (get_ttyp ()->ti.c_lflag & FLUSHO || !buf) continue; @@ -420,14 +429,17 @@ process_output (void *) for (;;) { int n = tty_master->process_slave_output (buf, OUT_BUFFER_SIZE, 0); - if (n <= 0) + if (n > 0) + { + n = tty_master->console->write ((void *) buf, (size_t) n); + tty_master->get_ttyp ()->write_error = n == -1 ? get_errno () : 0; + } + else { if (n < 0) termios_printf ("ReadFile %E"); ExitThread (0); } - n = tty_master->console->write ((void *) buf, (size_t) n); - tty_master->get_ttyp ()->write_error = n == -1 ? get_errno () : 0; } } @@ -454,9 +466,12 @@ process_ioctl (void *) /**********************************************************************/ /* Tty slave stuff */ -fhandler_tty_slave::fhandler_tty_slave () +fhandler_tty_slave::fhandler_tty_slave (int ntty) : fhandler_tty_common (), inuse (NULL) -{} +{ + if (ntty >= 0) + dev ().parse (DEV_TTYS_MAJOR, ntty); +} /* FIXME: This function needs to close handles when it has a failing condition. */ @@ -472,28 +487,13 @@ fhandler_tty_slave::open (int flags, mode_t) NULL }; - const char *errmsg = NULL; - for (HANDLE **h = handles; *h; h++) **h = NULL; - if (get_device () == FH_TTY) - dev().tty_to_real_device (); - fhandler_tty_slave *arch = (fhandler_tty_slave *) cygheap->fdtab.find_archetype (pc.dev); - if (arch) - { - *this = *(fhandler_tty_slave *) arch; - termios_printf ("copied fhandler_tty_slave archetype"); - set_flags ((flags & ~O_TEXT) | O_BINARY); - cygheap->manage_console_count ("fhandler_tty_slave::open", 1); - goto out; - } - tcinit (cygwin_shared->tty[get_unit ()], false); cygwin_shared->tty.attach (get_unit ()); - set_flags ((flags & ~O_TEXT) | O_BINARY); /* Create synchronisation events */ char buf[MAX_PATH]; @@ -505,6 +505,8 @@ fhandler_tty_slave::open (int flags, mode_t) shared_name (buf, OUTPUT_DONE_EVENT, get_unit ()); output_done_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf); + const char *errmsg = NULL; + if (!(output_mutex = get_ttyp ()->open_output_mutex (MAXIMUM_ALLOWED))) { errmsg = "open output mutex failed, %E"; @@ -646,19 +648,6 @@ fhandler_tty_slave::open (int flags, mode_t) if (cygheap->manage_console_count ("fhandler_tty_slave::open", 1) == 1 && !output_done_event) fhandler_console::need_invisible (); - - // FIXME: Do this better someday - arch = (fhandler_tty_slave *) cmalloc_abort (HEAP_ARCHETYPES, sizeof (*this)); - *((fhandler_tty_slave **) cygheap->fdtab.add_archetype ()) = arch; - archetype = arch; - *arch = *this; - -out: - usecount = 0; - arch->usecount++; - report_tty_counts (this, "opened", ""); - myself->set_ctty (get_ttyp (), flags, arch); - return 1; err: @@ -672,8 +661,17 @@ fhandler_tty_slave::open (int flags, mode_t) return 0; } -int -fhandler_tty_slave::close () +void +fhandler_tty_slave::open_setup (int flags) +{ + set_flags ((flags & ~O_TEXT) | O_BINARY); + myself->set_ctty (get_ttyp (), flags, this); + cygheap->manage_console_count ("fhandler_tty_slave::setup", 1); + report_tty_counts (this, "opened", ""); +} + +void +fhandler_tty_slave::cleanup () { /* This used to always call fhandler_tty_common::close when hExeced but that caused multiple closes of the handles associated with this tty. Since @@ -681,20 +679,12 @@ fhandler_tty_slave::close () or before a non-cygwin process has exited, it should be safe to just close this normally. cgf 2006-05-20 */ cygheap->manage_console_count ("fhandler_tty_slave::close", -1); - - archetype->usecount--; report_tty_counts (this, "closed", ""); +} - if (archetype->usecount) - { -#ifdef DEBUGGING - if (archetype->usecount < 0) - system_printf ("error: usecount %d", archetype->usecount); -#endif - termios_printf ("just returning because archetype usecount is != 0"); - return 0; - } - +int +fhandler_tty_slave::close () +{ termios_printf ("closing last open %s handle", ttyname ()); if (inuse && !CloseHandle (inuse)) termios_printf ("CloseHandle (inuse), %E"); @@ -702,7 +692,7 @@ fhandler_tty_slave::close () } int -fhandler_tty_slave::init (HANDLE f, DWORD a, mode_t) +fhandler_tty_slave::init (HANDLE h, DWORD a, mode_t) { int flags = 0; @@ -714,7 +704,7 @@ fhandler_tty_slave::init (HANDLE f, DWORD a, mode_t) if (a == (GENERIC_READ | GENERIC_WRITE)) flags = O_RDWR; - int ret = open (flags); + int ret = open_with_arch (flags); if (ret && !cygwin_finished_initializing && !being_debugged ()) { @@ -735,8 +725,8 @@ fhandler_tty_slave::init (HANDLE f, DWORD a, mode_t) } } - if (f != INVALID_HANDLE_VALUE) - CloseHandle (f); /* Reopened by open */ + if (h != INVALID_HANDLE_VALUE) + CloseHandle (h); /* Reopened by open */ return ret; } @@ -1037,38 +1027,14 @@ fhandler_tty_slave::read (void *ptr, size_t& len) int fhandler_tty_slave::dup (fhandler_base *child) { - fhandler_tty_slave *arch = (fhandler_tty_slave *) archetype; - /* In dtable::dup_worker, the path_conv member has already been assigned - from "this" to "child". Part of this assigment (path_conv::operator=) - is to allocate memory for the strings "path" and "normalized_path from - cygheap. The below `child = *arch' statement will overwrite child's - path_conv again, this time from "*arch". By doing that, it will allocate - new strings from cygheap, overwriting the old pointer values. Thus, the - old allocated strings are lost, and we're leaking memory for each tty dup, - unless we free the strings here. - FIXME: We can't redefine path_conv::operator= so that it frees the old - strings. Probably it would be most helpful to copy only the required - members from *arch, rather than copying everything. */ - child->pc.free_strings (); - *(fhandler_tty_slave *) child = *arch; - child->set_flags (get_flags ()); - child->usecount = 0; - arch->usecount++; cygheap->manage_console_count ("fhandler_tty_slave::dup", 1); - report_tty_counts (child, "duped", ""); + report_tty_counts (child, "duped slave", ""); return 0; } int fhandler_pty_master::dup (fhandler_base *child) { - fhandler_tty_master *arch = (fhandler_tty_master *) archetype; - /* See comment in fhandler_tty_slave::dup. */ - child->pc.free_strings (); - *(fhandler_tty_master *) child = *arch; - child->set_flags (get_flags ()); - child->usecount = 0; - arch->usecount++; report_tty_counts (child, "duped master", ""); return 0; } @@ -1435,15 +1401,8 @@ fhandler_pty_master::open (int flags, mode_t) set_flags ((flags & ~O_TEXT) | O_BINARY); set_open_status (); - /* FIXME: Do this better someday */ - fhandler_pty_master *arch = (fhandler_tty_master *) cmalloc_abort (HEAP_ARCHETYPES, sizeof (*this)); - *((fhandler_pty_master **) cygheap->fdtab.add_archetype ()) = arch; - archetype = arch; - *arch = *this; - arch->dwProcessId = GetCurrentProcessId (); + dwProcessId = GetCurrentProcessId (); - usecount = 0; - arch->usecount++; char buf[sizeof ("opened pty master for ttyNNNNNNNNNNN")]; __small_sprintf (buf, "opened pty master for tty%d", get_unit ()); report_tty_counts (this, buf, ""); @@ -1482,6 +1441,12 @@ fhandler_tty_common::close () return 0; } +void +fhandler_pty_master::cleanup () +{ + report_tty_counts (this, "closing master", ""); +} + int fhandler_pty_master::close () { @@ -1489,25 +1454,12 @@ fhandler_pty_master::close () while (accept_input () > 0) continue; #endif - archetype->usecount--; - report_tty_counts (this, "closing master", ""); - if (archetype->usecount) - { -#ifdef DEBUGGING - if (archetype->usecount < 0) - system_printf ("error: usecount %d", archetype->usecount); -#endif - termios_printf ("just returning because archetype usecount is != 0"); - return 0; - } - - fhandler_tty_master *arch = (fhandler_tty_master *) archetype; termios_printf ("closing from_master(%p)/to_master(%p) since we own them(%d)", - arch->from_master, arch->to_master, arch->dwProcessId); + from_master, to_master, dwProcessId); if (cygwin_finished_initializing) { - if (arch->master_ctl && get_ttyp ()->master_pid == myself->pid) + if (master_ctl && get_ttyp ()->master_pid == myself->pid) { char buf[MAX_PATH]; pipe_request req = { (DWORD) -1 }; @@ -1517,13 +1469,13 @@ fhandler_pty_master::close () __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl", &installation_key, get_unit ()); CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl, &len, 500); - CloseHandle (arch->master_ctl); - arch->master_thread->detach (); + CloseHandle (master_ctl); + master_thread->detach (); } - if (!ForceCloseHandle (arch->from_master)) - termios_printf ("error closing from_master %p, %E", arch->from_master); - if (!ForceCloseHandle (arch->to_master)) - termios_printf ("error closing from_master %p, %E", arch->to_master); + if (!ForceCloseHandle (from_master)) + termios_printf ("error closing from_master %p, %E", from_master); + if (!ForceCloseHandle (to_master)) + termios_printf ("error closing from_master %p, %E", to_master); } fhandler_tty_common::close (); @@ -1674,7 +1626,7 @@ fhandler_tty_slave::fixup_after_exec () int fhandler_tty_master::init_console () { - console = (fhandler_console *) build_fh_dev (*console_dev, "/dev/ttym"); + console = (fhandler_console *) build_fh_dev (*console_dev, "/dev/ttym_console"); if (console == NULL) return -1; @@ -1824,10 +1776,10 @@ fhandler_pty_master::pty_master_thread () } static DWORD WINAPI -pty_master_thread (VOID *arg) -{ +pty_master_thread (VOID *arg) +{ return ((fhandler_pty_master *) arg)->pty_master_thread (); -} +} bool fhandler_pty_master::setup (bool ispty) diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 2096475a94..820559e0f1 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -371,12 +371,33 @@ _pinfo::_ctty (char *buf) } void -_pinfo::set_ctty (tty_min *tc, int flags, fhandler_termios *arch) +_pinfo::set_ctty (tty_min *tc, int flags, fhandler_termios *fh) { - debug_printf ("old %s", __ctty ()); + debug_printf ("old %s, ctty %d, tc->ntty %d flags & O_NOCTTY %p", __ctty (), ctty, tc->ntty, flags & O_NOCTTY); if ((ctty < 0 || ctty == tc->ntty) && !(flags & O_NOCTTY)) { ctty = tc->ntty; + if (cygheap->ctty != fh->archetype) + { + debug_printf ("/dev/tty%d cygheap->ctty %p, archetype %p", ctty, cygheap->ctty, fh->archetype); + if (!cygheap->ctty) + syscall_printf ("ctty was NULL"); + else + { + syscall_printf ("ctty %p, usecount %d", cygheap->ctty, + cygheap->ctty->archetype_usecount (0)); + cygheap->ctty->close (); + } + cygheap->ctty = (fhandler_termios *) fh->archetype; + if (cygheap->ctty) + { + fh->archetype_usecount (1); + /* guard ctty fh */ + cygheap->manage_console_count ("_pinfo::set_ctty", 1); + report_tty_counts (cygheap->ctty, "ctty", ""); + } + } + 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 ()); @@ -399,28 +420,8 @@ _pinfo::set_ctty (tty_min *tc, int flags, fhandler_termios *arch) sid = tc->getsid (); if (tc->getpgid () == 0) tc->setpgid (pgid); - if (cygheap->ctty != arch) - { - debug_printf ("cygheap->ctty %p, arch %p", cygheap->ctty, arch); - if (!cygheap->ctty) - syscall_printf ("ctty NULL"); - else - { - syscall_printf ("ctty %p, usecount %d", cygheap->ctty, - cygheap->ctty->usecount); - cygheap->ctty->close (); - } - cygheap->ctty = arch; - if (arch) - { - arch->usecount++; - /* guard ctty arch */ - cygheap->manage_console_count ("_pinfo::set_ctty", 1); - report_tty_counts (cygheap->ctty, "ctty", ""); - } - } } - debug_printf ("cygheap->ctty now %p, arch %p", cygheap->ctty, arch); + debug_printf ("cygheap->ctty now %p, archetype %p", cygheap->ctty, fh->archetype); } /* Test to determine if a process really exists and is processing signals. diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 5585b332a7..d122c8dc27 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -101,7 +101,7 @@ close_all_files (bool norelease) DuplicateHandle (GetCurrentProcess (), fh->get_output_handle (), GetCurrentProcess (), &h, 0, false, DUPLICATE_SAME_ACCESS); - fh->close (); + fh->close_with_arch (); if (!norelease) cygheap->fdtab.release (i); } @@ -601,7 +601,7 @@ unlink_nt (path_conv &pc) NFS implements its own mechanism to remove in-use files which looks quite similar to what we do in try_to_bin for remote files. That's why we don't call try_to_bin on NFS. - + Netapp filesystems don't understand the "move and delete" method at all and have all kinds of weird effects. Just setting the delete dispositon usually works fine, though. */ @@ -721,7 +721,7 @@ unlink_nt (path_conv &pc) http://msdn.microsoft.com/en-us/library/ff545765%28VS.85%29.aspx "Subsequently, the only legal operation by such a caller is to close the open file handle." - + FIXME? On Vista and later, we could use FILE_HARD_LINK_INFORMATION to find all hardlinks and use one of them to restore the R/O bit, after the NtClose, but before we stop the transaction. This @@ -1107,25 +1107,18 @@ open (const char *unix_path, int flags, ...) res = -1; set_errno (EEXIST); } - else if (fh->is_fs_special () && fh->device_access_denied (flags)) + else if ((fh->is_fs_special () && fh->device_access_denied (flags)) + || !fh->open_with_arch (flags, (mode & 07777) & ~cygheap->umask)) { delete fh; res = -1; } else { - fh->close_on_exec (flags & O_CLOEXEC); - if (!fh->open (flags, (mode & 07777) & ~cygheap->umask)) - { - delete fh; - res = -1; - } - else - { - cygheap->fdtab[fd] = fh; - if ((res = fd) <= 2) - set_std_handle (res); - } + fd = fh; + if (fd <= 2) + set_std_handle (fd); + res = fd; } } } @@ -1185,7 +1178,7 @@ close (int fd) res = -1; else { - res = cfd->close (); + res = cfd->close_with_arch (); cfd.release (); } @@ -1974,7 +1967,7 @@ rename (const char *oldpath, const char *newpath) filename has one of the blessed executable suffixes. */ if (!old_explicit_suffix && oldpc.known_suffix && !newpc.is_binary () - && !nt_path_has_executable_suffix (newpc.get_nt_native_path ())) + && !nt_path_has_executable_suffix (newpc.get_nt_native_path ())) { rename_append_suffix (new2pc, newpath, nlen, ".exe"); removepc = &newpc; @@ -2040,7 +2033,7 @@ rename (const char *oldpath, const char *newpath) a temporary filename and then rename the temp filename to the target filename. This renaming fails due to the jealous virus scanner and the application fails to create the target file. - + This kludge tries to work around that by yielding until the sharing violation goes away, or a signal arrived, or after about a second, give or take. */