summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <cgf@redhat.com>2004-11-21 04:39:12 +0000
committerChristopher Faylor <cgf@redhat.com>2004-11-21 04:39:12 +0000
commitb672e14da40309c3dc402cb605ca5150d812f6ad (patch)
treef366032b4585c169fffaaceb4eece838a19b7c28
parent02abf3460335791ef947a3934c80e13a87175145 (diff)
downloadgdb-b672e14da40309c3dc402cb605ca5150d812f6ad.tar.gz
* 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".
-rw-r--r--winsup/cygwin/ChangeLog13
-rw-r--r--winsup/cygwin/cygheap.h392
-rw-r--r--winsup/cygwin/pinfo.cc11
-rw-r--r--winsup/cygwin/pinfo.h5
-rw-r--r--winsup/cygwin/spawn.cc4
5 files changed, 422 insertions, 3 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 02010f1a09c..0fe827baa8c 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,18 @@
2004-11-20 Christopher Faylor <cgf@timesys.com>
+ * 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".
+
+2004-11-20 Christopher Faylor <cgf@timesys.com>
+
* pinfo.h (pinfo::alert_parent): New function.
* exceptions.cc (sig_handle_tty_stop): Use alert_parent to send
"signals" to parent.
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
new file mode 100644
index 00000000000..63514514b0a
--- /dev/null
+++ b/winsup/cygwin/cygheap.h
@@ -0,0 +1,392 @@
+/* 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;
+ }
+ }
+ 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;
+}
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 6af9cd647ba..acab4e526b6 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -59,14 +59,18 @@ set_myself (HANDLE h)
myself->dwProcessId = GetCurrentProcessId ();
if (h)
{
+ /* here if execed */
static pinfo NO_COPY myself_identity;
myself_identity.init (cygwin_pid (myself->dwProcessId), PID_EXECED);
}
else if (myself->ppid)
{
+ /* here if forked/spawned */
pinfo parent (myself->ppid);
if (parent && parent->wr_proc_pipe)
CloseHandle (parent->wr_proc_pipe);
+ if (cygheap->pid_handle)
+ CloseHandle (cygheap->pid_handle);
}
return;
}
@@ -784,6 +788,13 @@ pinfo::wait ()
hProcess);
return 0;
}
+ if (!DuplicateHandle (hMainProc, hProcess, hMainProc, &pid_handle, 0,
+ FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid,
+ hProcess);
+ return 0;
+ }
CloseHandle (out);
preserve ();
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
index a0cf36383d5..8c4784d9dcc 100644
--- a/winsup/cygwin/pinfo.h
+++ b/winsup/cygwin/pinfo.h
@@ -40,9 +40,6 @@ public:
#define PINFO_REDIR_SIZE ((char *) &myself.procinfo->exitcode - (char *) myself.procinfo)
- /* Handle associated with initial Windows pid which started it all. */
- HANDLE pid_handle;
-
/* > 0 if started by a cygwin process */
DWORD cygstarted;
@@ -130,6 +127,8 @@ public:
HANDLE rd_proc_pipe;
HANDLE hProcess;
CRITICAL_SECTION lock;
+ /* Handle associated with initial Windows pid which started it all. */
+ HANDLE pid_handle;
void init (pid_t, DWORD, HANDLE = NULL) __attribute__ ((regparm(3)));
pinfo () {}
pinfo (_pinfo *x): procinfo (x) {}
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index bebbf22ca3f..99ff063fc43 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -624,6 +624,10 @@ spawn_guts (const char * prog_arg, const char *const *argv,
{
saved_sendsig = myself->sendsig;
myself->sendsig = INVALID_HANDLE_VALUE;
+ if (!cygheap->pid_handle
+ && !DuplicateHandle (hMainProc, hMainProc, hMainProc, &cygheap->pid_handle,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ system_printf ("duplicate to pid_handle failed, %E");
}
/* Some file types (currently only sockets) need extra effort in the