mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-28 10:00:23 +08:00
8cb359d947
* dcrt0.cc (dll_crt0_0): Remove hexec_proc stuff. * fork.cc (fork_child): Remove call to pinfo_fixup_after_fork. * pinfo.cc (set_myself): Close and zero pid_handle if set. (pinfo_fixup_after_fork): Delete. (proc_waiter): Don't close vchild.hProcess here. Do that when we are remove the vchild from procs. Save hProcess as pid_handle only on first reparent operation. (pinfo::wait): Don't set pid_handle here. (pinfo::alert_parent): Always try to send signal. If unsuccessful then close and zero wr_proc_pipe. * pinfo.h (pinfo::pinfo): Make sure that appropriate parts of the class are zeroed on construction. (pinfo::alert_parent): Take char argument. (pinfo_fixup_after_fork): Delete declaration. (hexec_proc): Ditto. * sigproc.cc (remove_proc): Close pid_handle and hProcess if appropriate. * spawn.cc (spawn_guts): Set cygheap->pid_handle on first exec. * cygheap.h (init_cygheap::pid_handle): New element. * pinfo.cc (set_myself): Clear previously existing cygheap->pid_handle when a new process has been started. (pinfo::wait): Make sure that a handle to the newly forked/spawned process is kept around so that the pid will not be reused. * pinfo.h (_pinfo::pid_handle): Move. (pinfo::pid_handle): to here. * spawn.cc (spawn_guts): Create a pid_handle in cygheap prior to spawning to ensure that the pid does not get reused during the lifetime of the "cygwin pid". * pinfo.h (pinfo::alert_parent): New function. * exceptions.cc (sig_handle_tty_stop): Use alert_parent to send "signals" to parent. * fork.cc (fork_parent): Don't close pi.hProcess. Let the waiter thread do that. * pinfo.cc (proc_waiter): Detect case where process exits without setting the exit code and use value from GetExitCodeProcess. Reluctantly implement __SIGREPARENT. (pinfo::alert_parent): Define. * sigproc.h (__SIGREPARENT): New enum. * spawn.cc (spawn_guts): Send reparent signal to parent on exec. Always create process in suspended state to avoid races. Remove cygthread.h in favor of cygtls.h throughout since cygtls now includes cygthread.h. Eliminate ppid_handle usage throughout. * child_info.h: Regenerate magic number (child_info): Remove pppid_handle. * cygthread.h (cygthread::release): New method. Frees thread without waiting. * cygthread.cc (cygthread::stub): Set _ctinfo in _mytls to point to information for executing thread. Don't call SetEvent if thread is no longer in use. (cygthread::simplestub): Ditto. * cygtls.h (_cygtls::_ctinfo): New element contains pointer to information about executing cygthread, if any. * dcrt0.cc: Remove last vestiges of per_thread stuff. (dll_crt0_0): Ditto. Remove accommodation for ppid_handle. (do_exit): Remove obsolete reparenting test. (_exit): Exit with a more SUSv3-like exit value. * dtable.cc (dtable::stdio_init): Check for myself->cygstarted rather than myself->ppid_handle to see if we were started by a cygwin process. * exceptions.cc (open_stackdumpfile): Ditto. (handle_exceptions): Ditto. (ctrl_c_handler): Ditto. (sig_handle_tty_stop): Ditto. Let parent send signal to itself on STOP. (sigpacket::process): Comment out vfork test. (signal_exit): Use more SUSv3-like exit value on signal. * external.cc (fillout_pinfo): Don't set hProcess. * fork.cc: Remove VFORK cruft. (per_thread::set): Delete. (fork_child): Remove perthread stuff. (fork_parent): Remove obsolete subproc_init. Accommodate new method for tracking subprocesses. * pinfo.cc (set_myself): Accommodate new pinfo/_pinfo layout. Set some things here that used to be set in wait_sig. (_pinfo::exit): Set exitcode here. Close process pipe. (_pinfo::commune_send): Accommodeate new pinfo/_pinfo layout. (proc_waiter): New function. Waits, in a thread for subprocess to go away. (pinfo::wait): New function. Initialization for proc_waiter. * pinfo.h (_pinfo::exitcode): New element. (_pinfo::cygstarted): Ditto. (_pinfo::wr_proc_pipe): Ditto. (_pinfo::ppid_handle): Delete. (_pinfo::hProcess): Delete. (_pinfo::lock): Delete. (pinfo::hProcess): New element. (pinfo::lock): Ditto. (pinfo::wait): Declare new function. (pinfo::preserve): Define new function. * sigproc.cc: Remove old stuff from wait_subproc thread based method. (zombies): Remove. (procs): New. (my_parent_is_alive): Just check that the parent pid exists. (mychild): Just use pinfo methods to determine if child is mine. (proc_subproc): Revamp PROC_ADDCHILD to use pinfo::wait. Remove PROC_CHILDTERMINATED logic. Use different method to remove processes from list when SIGCHLD == SIG_IGN. (proc_terminate): Gut. (subproc_init): Delete. (init_child_info): Remove setting of pppid_handle. (checkstate): Revamp to only scan procs array. (remove_proc): Rename from remove_zombie. Don't close hProcess or pid_handle. Don't release memory if it's myself. (stopped_or_terminated): Change logic to handle new consolidated proc/zombie array. (wait_subproc): Delete. * sigproc.h: Remove obsolete EXIT_* defines. (subproc_init): Remove declaration. * spawn.cc (spawn_guts): Remove reparenting stuff. Use standard wait logic to wait for child if started from a non-cygwin process. * tlsoffsets.h: Regenerate. * tty.cc (tty_init): Check for myself->cygstarted rather than myself->ppid_handle to see if we were started by a cygwin process. * include/sys/signal.h (external_pinfo::exitcode): Replace hProcess. * include/sys/wait.h (WCOREDUMP): Define. * fhandler_tty.cc (fhandler_tty_slave::read): Add debugging output for timeout case. * signal.cc (abort): Flag that we are exiting with the ABORT signal.
401 lines
10 KiB
C++
401 lines
10 KiB
C++
/* cygheap.h: Cygwin heap manager.
|
|
|
|
Copyright 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
|
|
|
|
This file is part of Cygwin.
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
details. */
|
|
|
|
#undef cfree
|
|
|
|
enum cygheap_types
|
|
{
|
|
HEAP_FHANDLER,
|
|
HEAP_STR,
|
|
HEAP_ARGV,
|
|
HEAP_BUF,
|
|
HEAP_MOUNT,
|
|
HEAP_SIGS,
|
|
HEAP_ARCHETYPES,
|
|
HEAP_TLS,
|
|
HEAP_1_START,
|
|
HEAP_1_STR,
|
|
HEAP_1_ARGV,
|
|
HEAP_1_BUF,
|
|
HEAP_1_EXEC,
|
|
HEAP_1_MAX = 100,
|
|
HEAP_MMAP = 200
|
|
};
|
|
|
|
#define incygheap(s) (cygheap && ((char *) (s) >= (char *) cygheap) && ((char *) (s) <= ((char *) cygheap_max)))
|
|
|
|
struct _cmalloc_entry
|
|
{
|
|
union
|
|
{
|
|
DWORD b;
|
|
char *ptr;
|
|
};
|
|
struct _cmalloc_entry *prev;
|
|
char data[0];
|
|
};
|
|
|
|
struct cygheap_root_mount_info
|
|
{
|
|
char posix_path[CYG_MAX_PATH];
|
|
unsigned posix_pathlen;
|
|
char native_path[CYG_MAX_PATH];
|
|
unsigned native_pathlen;
|
|
};
|
|
|
|
/* CGF: FIXME This doesn't belong here */
|
|
|
|
class cygheap_root
|
|
{
|
|
/* Root directory information.
|
|
This is used after a chroot is called. */
|
|
struct cygheap_root_mount_info *m;
|
|
|
|
public:
|
|
bool posix_ok (const char *path)
|
|
{
|
|
if (!m)
|
|
return 1;
|
|
return path_prefix_p (m->posix_path, path, m->posix_pathlen);
|
|
}
|
|
bool ischroot_native (const char *path)
|
|
{
|
|
if (!m)
|
|
return 1;
|
|
return strncasematch (m->native_path, path, m->native_pathlen)
|
|
&& (path[m->native_pathlen] == '\\' || !path[m->native_pathlen]);
|
|
}
|
|
const char *unchroot (const char *path)
|
|
{
|
|
if (!m)
|
|
return path;
|
|
const char *p = path + m->posix_pathlen;
|
|
if (!*p)
|
|
p = "/";
|
|
return p;
|
|
}
|
|
bool exists () {return !!m;}
|
|
void set (const char *, const char *);
|
|
size_t posix_length () const { return m->posix_pathlen; }
|
|
const char *posix_path () const { return m->posix_path; }
|
|
size_t native_length () const { return m->native_pathlen; }
|
|
const char *native_path () const { return m->native_path; }
|
|
};
|
|
|
|
enum homebodies
|
|
{
|
|
CH_HOMEDRIVE,
|
|
CH_HOMEPATH,
|
|
CH_HOME
|
|
};
|
|
|
|
class cygheap_user
|
|
{
|
|
/* Extendend user information.
|
|
The information is derived from the internal_getlogin call
|
|
when on a NT system. */
|
|
char *pname; /* user's name */
|
|
char *plogsrv; /* Logon server, may be FQDN */
|
|
char *pdomain; /* Logon domain of the user */
|
|
char *homedrive; /* User's home drive */
|
|
char *homepath; /* User's home path */
|
|
char *psystemroot; /* Value of SYSTEMROOT */
|
|
char *pwinname; /* User's name as far as Windows knows it */
|
|
char *puserprof; /* User profile */
|
|
cygsid effec_cygsid; /* buffer for user's SID */
|
|
cygsid saved_cygsid; /* Remains intact even after impersonation */
|
|
public:
|
|
__uid32_t saved_uid; /* Remains intact even after impersonation */
|
|
__gid32_t saved_gid; /* Ditto */
|
|
__uid32_t real_uid; /* Remains intact on seteuid, replaced by setuid */
|
|
__gid32_t real_gid; /* Ditto */
|
|
user_groups groups; /* Primary and supp SIDs */
|
|
|
|
/* token is needed if set(e)uid should be called. It can be set by a call
|
|
to `set_impersonation_token()'. */
|
|
HANDLE external_token;
|
|
HANDLE internal_token;
|
|
HANDLE current_token;
|
|
|
|
/* CGF 2002-06-27. I removed the initializaton from this constructor
|
|
since this class is always allocated statically. That means that everything
|
|
is zero anyway so there is no need to initialize it to zero. Since the
|
|
token initialization is always handled during process startup as well,
|
|
I've removed the constructor entirely. Please reinstate this if this
|
|
situation ever changes.
|
|
cygheap_user () : pname (NULL), plogsrv (NULL), pdomain (NULL),
|
|
homedrive (NULL), homepath (NULL),
|
|
token (INVALID_HANDLE_VALUE) {}
|
|
*/
|
|
|
|
~cygheap_user ();
|
|
|
|
void init ();
|
|
void set_name (const char *new_name);
|
|
const char *name () const { return pname; }
|
|
|
|
const char *env_logsrv (const char *, size_t);
|
|
const char *env_homepath (const char *, size_t);
|
|
const char *env_homedrive (const char *, size_t);
|
|
const char *env_userprofile (const char *, size_t);
|
|
const char *env_domain (const char *, size_t);
|
|
const char *env_name (const char *, size_t);
|
|
const char *env_systemroot (const char *, size_t);
|
|
|
|
const char *logsrv ()
|
|
{
|
|
const char *p = env_logsrv ("LOGONSERVER=", sizeof ("LOGONSERVER=") - 1);
|
|
return (p == almost_null) ? NULL : p;
|
|
}
|
|
const char *winname ()
|
|
{
|
|
const char *p = env_name ("USERNAME=", sizeof ("USERNAME=") - 1);
|
|
return (p == almost_null) ? NULL : p;
|
|
}
|
|
const char *domain ()
|
|
{
|
|
const char *p = env_domain ("USERDOMAIN=", sizeof ("USERDOMAIN=") - 1);
|
|
return (p == almost_null) ? NULL : p;
|
|
}
|
|
BOOL set_sid (PSID new_sid) {return (BOOL) (effec_cygsid = new_sid);}
|
|
BOOL set_saved_sid () { return (BOOL) (saved_cygsid = effec_cygsid); }
|
|
PSID sid () { return effec_cygsid; }
|
|
PSID saved_sid () { return saved_cygsid; }
|
|
const char *ontherange (homebodies what, struct passwd * = NULL);
|
|
#define NO_IMPERSONATION NULL
|
|
bool issetuid () const { return current_token != NO_IMPERSONATION; }
|
|
HANDLE token () { return current_token; }
|
|
void deimpersonate ()
|
|
{
|
|
if (issetuid ())
|
|
RevertToSelf ();
|
|
}
|
|
void reimpersonate ()
|
|
{
|
|
if (issetuid ()
|
|
&& !ImpersonateLoggedOnUser (token ()))
|
|
system_printf ("ImpersonateLoggedOnUser: %E");
|
|
}
|
|
bool has_impersonation_tokens ()
|
|
{ return external_token != NO_IMPERSONATION
|
|
|| internal_token != NO_IMPERSONATION
|
|
|| current_token != NO_IMPERSONATION; }
|
|
void close_impersonation_tokens ()
|
|
{
|
|
if (current_token != NO_IMPERSONATION)
|
|
{
|
|
if( current_token != external_token && current_token != internal_token)
|
|
CloseHandle (current_token);
|
|
current_token = NO_IMPERSONATION;
|
|
}
|
|
if (external_token != NO_IMPERSONATION)
|
|
{
|
|
CloseHandle (external_token);
|
|
external_token = NO_IMPERSONATION;
|
|
}
|
|
if (internal_token != NO_IMPERSONATION)
|
|
{
|
|
CloseHandle (internal_token);
|
|
internal_token = NO_IMPERSONATION;
|
|
}
|
|
}
|
|
char * get_windows_id (char * buf)
|
|
{
|
|
if (wincap.is_winnt ())
|
|
return effec_cygsid.string (buf);
|
|
else
|
|
return strcpy (buf, name ());
|
|
}
|
|
|
|
const char *cygheap_user::test_uid (char *&, const char *, size_t)
|
|
__attribute__ ((regparm (3)));
|
|
};
|
|
|
|
/* cwd cache stuff. */
|
|
|
|
class muto;
|
|
|
|
struct cwdstuff
|
|
{
|
|
char *posix;
|
|
char *win32;
|
|
DWORD hash;
|
|
DWORD drive_length;
|
|
muto *cwd_lock;
|
|
char *get (char *, int = 1, int = 0, unsigned = CYG_MAX_PATH);
|
|
DWORD get_hash ();
|
|
DWORD get_drive (char * dst)
|
|
{
|
|
get_initial ();
|
|
memcpy (dst, win32, drive_length);
|
|
return drive_length;
|
|
}
|
|
void init ();
|
|
void fixup_after_exec (char *, char *, DWORD);
|
|
bool get_initial ();
|
|
int set (const char *, const char *, bool);
|
|
};
|
|
|
|
#ifdef DEBUGGING
|
|
struct cygheap_debug
|
|
{
|
|
handle_list starth;
|
|
handle_list *endh;
|
|
handle_list freeh[500];
|
|
};
|
|
#endif
|
|
|
|
struct user_heap_info
|
|
{
|
|
void *base;
|
|
void *ptr;
|
|
void *top;
|
|
void *max;
|
|
unsigned chunk;
|
|
};
|
|
|
|
struct init_cygheap
|
|
{
|
|
_cmalloc_entry *chain;
|
|
char *buckets[32];
|
|
cygheap_root root;
|
|
cygheap_user user;
|
|
user_heap_info user_heap;
|
|
mode_t umask;
|
|
HANDLE shared_h;
|
|
HANDLE console_h;
|
|
HANDLE mt_h;
|
|
char *cygwin_regname;
|
|
cwdstuff cwd;
|
|
dtable fdtab;
|
|
const char *shared_prefix;
|
|
#ifdef DEBUGGING
|
|
cygheap_debug debug;
|
|
#endif
|
|
struct sigaction *sigs;
|
|
|
|
fhandler_tty_slave *ctty; /* Current tty */
|
|
#ifdef NEWVFORK
|
|
fhandler_tty_slave *ctty_on_hold;
|
|
#endif
|
|
struct _cygtls **threadlist;
|
|
size_t sthreads;
|
|
int open_fhs;
|
|
pid_t pid; /* my pid */
|
|
HANDLE pid_handle; /* handle for my pid */
|
|
void close_ctty ();
|
|
};
|
|
|
|
#define _CYGHEAPSIZE_SLOP (128 * 1024)
|
|
#define CYGHEAPSIZE (sizeof (init_cygheap) + (20000 * sizeof (fhandler_union)) + _CYGHEAPSIZE_SLOP)
|
|
#define CYGHEAPSIZE_MIN (sizeof (init_cygheap) + (10000 * sizeof (fhandler_union)))
|
|
|
|
extern init_cygheap *cygheap;
|
|
extern void *cygheap_max;
|
|
|
|
class cygheap_fdmanip
|
|
{
|
|
protected:
|
|
int fd;
|
|
fhandler_base **fh;
|
|
bool locked;
|
|
public:
|
|
cygheap_fdmanip (): fh (NULL) {}
|
|
virtual ~cygheap_fdmanip ()
|
|
{
|
|
if (locked)
|
|
cygheap->fdtab.unlock ();
|
|
}
|
|
void release ()
|
|
{
|
|
cygheap->fdtab.release (fd);
|
|
}
|
|
operator int &() {return fd;}
|
|
operator fhandler_base* &() {return *fh;}
|
|
operator fhandler_socket* () const {return reinterpret_cast<fhandler_socket *> (*fh);}
|
|
void operator = (fhandler_base *fh) {*this->fh = fh;}
|
|
fhandler_base *operator -> () const {return *fh;}
|
|
bool isopen () const
|
|
{
|
|
if (*fh)
|
|
return true;
|
|
set_errno (EBADF);
|
|
return false;
|
|
}
|
|
};
|
|
|
|
class cygheap_fdnew : public cygheap_fdmanip
|
|
{
|
|
public:
|
|
cygheap_fdnew (int seed_fd = -1, bool lockit = true)
|
|
{
|
|
if (lockit)
|
|
cygheap->fdtab.lock ();
|
|
if (seed_fd < 0)
|
|
fd = cygheap->fdtab.find_unused_handle ();
|
|
else
|
|
fd = cygheap->fdtab.find_unused_handle (seed_fd + 1);
|
|
if (fd >= 0)
|
|
{
|
|
locked = lockit;
|
|
fh = cygheap->fdtab + fd;
|
|
}
|
|
else
|
|
{
|
|
set_errno (EMFILE);
|
|
if (lockit)
|
|
cygheap->fdtab.unlock ();
|
|
locked = false;
|
|
}
|
|
}
|
|
void operator = (fhandler_base *fh) {*this->fh = fh;}
|
|
};
|
|
|
|
class cygheap_fdget : public cygheap_fdmanip
|
|
{
|
|
public:
|
|
cygheap_fdget (int fd, bool lockit = false, bool do_set_errno = true)
|
|
{
|
|
if (lockit)
|
|
cygheap->fdtab.lock ();
|
|
if (fd >= 0 && fd < (int) cygheap->fdtab.size
|
|
&& *(fh = cygheap->fdtab + fd) != NULL)
|
|
{
|
|
this->fd = fd;
|
|
locked = lockit;
|
|
}
|
|
else
|
|
{
|
|
this->fd = -1;
|
|
if (do_set_errno)
|
|
set_errno (EBADF);
|
|
if (lockit)
|
|
cygheap->fdtab.unlock ();
|
|
locked = false;
|
|
}
|
|
}
|
|
};
|
|
|
|
class child_info;
|
|
void *__stdcall cygheap_setup_for_child (child_info *ci, bool dup_later) __attribute__ ((regparm(2)));
|
|
void __stdcall cygheap_setup_for_child_cleanup (void *, child_info *, bool) __attribute__ ((regparm(3)));
|
|
void __stdcall cygheap_fixup_in_child (bool);
|
|
extern "C" {
|
|
void __stdcall cfree (void *) __attribute__ ((regparm(1)));
|
|
void *__stdcall cmalloc (cygheap_types, DWORD) __attribute__ ((regparm(2)));
|
|
void *__stdcall crealloc (void *, DWORD) __attribute__ ((regparm(2)));
|
|
void *__stdcall ccalloc (cygheap_types, DWORD, DWORD) __attribute__ ((regparm(3)));
|
|
char *__stdcall cstrdup (const char *) __attribute__ ((regparm(1)));
|
|
char *__stdcall cstrdup1 (const char *) __attribute__ ((regparm(1)));
|
|
void __stdcall cfree_and_set (char *&, char * = NULL) __attribute__ ((regparm(2)));
|
|
void __stdcall cygheap_init ();
|
|
extern DWORD _cygheap_start;
|
|
}
|