From 363934dc9b9327460fefc113a3797e7e51ea2c18 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Mon, 12 Dec 2005 18:43:31 +0000 Subject: [PATCH] * pinfo.cc (size_copied): New convenience macro. (winpids::add): Alias the element that we are working on for slightly better clarity. Honor the "make_copy" flag. (winpids::release): Free and zero procinfo field if it was allocated via malloc. (winpids::~winpids): Free copied array. * pinfo.h (class pinfo): Make winpids class a friend. (winpids::make_copy): New field. (winpids::copied): New array. (winpids::reset): Reset npids after releasing pinfos or suffer a memory leak. (winpids::winpids): Try harder to allocate all fields in the class. --- winsup/cygwin/ChangeLog | 15 +++++++++++++++ winsup/cygwin/pinfo.cc | 42 +++++++++++++++++++++++++++++++++-------- winsup/cygwin/pinfo.h | 20 ++++++++++++-------- 3 files changed, 61 insertions(+), 16 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 594744d40..bb49e7578 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,18 @@ +2005-12-12 Christopher Faylor + + * pinfo.cc (size_copied): New convenience macro. + (winpids::add): Alias the element that we are working on for slightly + better clarity. Honor the "make_copy" flag. + (winpids::release): Free and zero procinfo field if it was allocated + via malloc. + (winpids::~winpids): Free copied array. + * pinfo.h (class pinfo): Make winpids class a friend. + (winpids::make_copy): New field. + (winpids::copied): New array. + (winpids::reset): Reset npids after releasing pinfos or suffer a memory + leak. + (winpids::winpids): Try harder to allocate all fields in the class. + 2005-12-12 Corinna Vinschen * autoload.cc (GetSystemTimes): Remove. diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index fb3c9da14..4e8f1a899 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -1089,6 +1089,7 @@ cygwin_winpid_to_pid (int winpid) #define slop_pidlist 200 #define size_pidlist(i) (sizeof (pidlist[0]) * ((i) + 1)) #define size_pinfolist(i) (sizeof (pinfolist[0]) * ((i) + 1)) +#define size_copied(i) (sizeof (copied[0]) * ((i) + 1)) inline void winpids::add (DWORD& nelem, bool winpid, DWORD pid) @@ -1097,34 +1098,51 @@ winpids::add (DWORD& nelem, bool winpid, DWORD pid) if (nelem >= npidlist) { npidlist += slop_pidlist; + copied = (bool *) realloc (copied, size_copied (npidlist + 1)); pidlist = (DWORD *) realloc (pidlist, size_pidlist (npidlist + 1)); pinfolist = (pinfo *) realloc (pinfolist, size_pinfolist (npidlist + 1)); } - pinfolist[nelem].init (cygpid, PID_NOREDIR | pinfo_access, NULL); + pinfo& p = pinfolist[nelem]; + + p.init (cygpid, PID_NOREDIR | pinfo_access, NULL); if (winpid) goto out; - if (!pinfolist[nelem]) + if (!p) { if (!pinfo_access) return; - pinfolist[nelem].init (cygpid, PID_NOREDIR, NULL); - if (!pinfolist[nelem]) + p.init (cygpid, PID_NOREDIR, NULL); + if (!p) return; } /* Scan list of previously recorded pids to make sure that this pid hasn't shown up before. This can happen when a process execs. */ for (unsigned i = 0; i < nelem; i++) - if (pinfolist[i]->pid == pinfolist[nelem]->pid) + if (pinfolist[i]->pid == p->pid) { - if ((_pinfo *) pinfolist[nelem] != (_pinfo *) myself) - pinfolist[nelem].release (); + if ((_pinfo *) p != (_pinfo *) myself) + p.release (); return; } out: + copied[nelem] = false; + if (make_copy) + { + _pinfo *pnew = (_pinfo *) malloc (sizeof (*p.procinfo)); + if (pnew) + { + copied[nelem] = true; + *pnew = *p.procinfo; + if ((_pinfo *) p != (_pinfo *) myself) + p.release (); + p.procinfo = pnew; + p.destroy = false; + } + } pidlist[nelem++] = pid; } @@ -1219,9 +1237,16 @@ winpids::enum_init (bool winpid) void winpids::release () { + _pinfo *p; for (unsigned i = 0; i < npids; i++) if (pinfolist[i] && (_pinfo *) pinfolist[i] != (_pinfo *) myself) - pinfolist[i].release (); + if (!copied[i]) + pinfolist[i].release (); + else if ((p = pinfolist[i].procinfo)) + { + pinfolist[i].procinfo = NULL; + free (p); + } } winpids::~winpids () @@ -1229,6 +1254,7 @@ winpids::~winpids () if (npidlist) { release (); + free (copied); free (pidlist); free (pinfolist); } diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h index d0c634909..6c701d5a8 100644 --- a/winsup/cygwin/pinfo.h +++ b/winsup/cygwin/pinfo.h @@ -193,6 +193,7 @@ public: void set_acl (); void zap_cwd (); friend class _pinfo; + friend class winpids; }; #define ISSTATE(p, f) (!!((p)->process_state & f)) @@ -200,9 +201,11 @@ public: class winpids { - DWORD *pidlist; + bool make_copy; DWORD npidlist; + DWORD *pidlist; pinfo *pinfolist; + bool *copied; DWORD pinfo_access; // access type for pinfo open DWORD (winpids::* enum_processes) (bool winpid); DWORD enum_init (bool winpid); @@ -211,15 +214,16 @@ class winpids void add (DWORD& nelem, bool, DWORD pid); public: DWORD npids; - inline void reset () { npids = 0; release (); } + inline void reset () { release (); npids = 0;} void set (bool winpid); - winpids (): enum_processes (&winpids::enum_init) {} - winpids (int): pinfo_access (0), enum_processes (&winpids::enum_init) - { reset (); } - winpids (DWORD acc): pidlist (NULL), npidlist (0), pinfolist (NULL), - enum_processes (&winpids::enum_init), npids (0) + winpids (): make_copy (true), enum_processes (&winpids::enum_init) {} + winpids (int): make_copy (false), npidlist (0), pidlist (NULL), pinfolist (NULL), + copied (NULL), pinfo_access (0), enum_processes (&winpids::enum_init), + npids (0) {} + winpids (DWORD acc): make_copy (false), npidlist (0), pidlist (NULL), pinfolist (NULL), + copied (NULL), pinfo_access (acc), enum_processes (&winpids::enum_init), + npids (0) { - pinfo_access = acc; set (0); } inline DWORD& winpid (int i) const {return pidlist[i];}