OSDN Git Service

9acb54b1e45406bf9a07bda8fa3c355b92159a85
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / debug.cc
1 /* debug.cc
2
3    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4    2008, 2009, 2011
5    Red Hat, Inc.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 #include "winsup.h"
12 #include "cygerrno.h"
13 #ifdef DEBUGGING
14 #include "path.h"
15 #include "fhandler.h"
16 #include "dtable.h"
17 #include "cygheap.h"
18 #endif
19
20 #undef CloseHandle
21
22 #ifdef DEBUGGING
23 /* Here lies extra debugging routines which help track down internal
24    Cygwin problems when compiled with -DDEBUGGING . */
25 #define NFREEH (sizeof (cygheap->debug.freeh) / sizeof (cygheap->debug.freeh[0]))
26
27 class lock_debug
28 {
29   static muto locker;
30  public:
31   lock_debug ()
32   {
33     locker.acquire (INFINITE);
34   }
35   void unlock ()
36   {
37     locker.release ();
38   }
39   ~lock_debug () {unlock ();}
40   friend void debug_init ();
41 };
42
43 muto NO_COPY lock_debug::locker;
44
45 static bool __stdcall mark_closed (const char *, int, HANDLE, const char *, bool);
46
47 void
48 debug_init ()
49 {
50   lock_debug::locker.init ("debug_lock");
51 }
52
53 /* Find a registered handle in the linked list of handles. */
54 static handle_list * __stdcall
55 find_handle (HANDLE h)
56 {
57   handle_list *hl;
58   for (hl = &cygheap->debug.starth; hl->next != NULL; hl = hl->next)
59     if (hl->next->h == h)
60       goto out;
61   hl = NULL;
62
63 out:
64   return hl;
65 }
66
67 void
68 verify_handle (const char *func, int ln, HANDLE h)
69 {
70   lock_debug here;
71   handle_list *hl = find_handle (h);
72   if (!hl)
73     return;
74   system_printf ("%s:%d - multiple attempts to add handle %p", func, ln, h);
75
76   system_printf (" previously allocated by %s:%d(%s<%p>) winpid %d",
77                  hl->func, hl->ln, hl->name, hl->h, hl->pid);
78 }
79
80 void
81 setclexec (HANDLE oh, HANDLE nh, bool not_inheriting)
82 {
83   lock_debug here;
84   handle_list *hl = find_handle (oh);
85   if (hl)
86     {
87       hl = hl->next;
88       hl->inherited = !not_inheriting;
89       hl->h = nh;
90     }
91 }
92
93 /* Create a new handle record */
94 static handle_list * __stdcall
95 newh ()
96 {
97   handle_list *hl;
98
99   for (hl = cygheap->debug.freeh; hl < cygheap->debug.freeh + NFREEH; hl++)
100     if (hl->name == NULL)
101       return hl;
102
103   return NULL;
104 }
105
106 void __stdcall
107 modify_handle (const char *func, int ln, HANDLE h, const char *name, bool inh)
108 {
109   lock_debug here;
110   handle_list *hl = find_handle (h);
111   if (!hl)
112     {
113       system_printf ("%s:%d handle %s<%p> not found", func, ln, name, h);
114       return;
115     }
116   hl->next->inherited = inh;
117   debug_printf ("%s:%d set handle %s<%p> inheritance flag to %d", func, ln,
118                 name, h, inh);
119 }
120
121 /* Add a handle to the linked list of known handles. */
122 void __stdcall
123 add_handle (const char *func, int ln, HANDLE h, const char *name, bool inh)
124 {
125   handle_list *hl;
126
127   if (!cygheap)
128     return;
129
130   lock_debug here;
131   if ((hl = find_handle (h)))
132     {
133       hl = hl->next;
134       if (hl->name == name && hl->func == func && hl->ln == ln)
135         return;
136       system_printf ("%s:%d - multiple attempts to add handle %s<%p>", func,
137                      ln, name, h);
138       system_printf (" previously allocated by %s:%d(%s<%p>) winpid %d",
139                      hl->func, hl->ln, hl->name, hl->h, hl->pid);
140       return;
141     }
142
143   if ((hl = newh ()) == NULL)
144     {
145       here.unlock ();
146       debug_printf ("couldn't allocate memory for %s(%d): %s(%p)",
147                     func, ln, name, h);
148       return;
149     }
150   hl->h = h;
151   hl->name = name;
152   hl->func = func;
153   hl->ln = ln;
154   hl->inherited = inh;
155   hl->pid = GetCurrentProcessId ();
156   hl->next = cygheap->debug.starth.next;
157   cygheap->debug.starth.next = hl;
158   SetHandleInformation (h, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE);
159   debug_printf ("protecting handle '%s'(%p), inherited flag %d", hl->name, hl->h, hl->inherited);
160 }
161
162 static void __stdcall
163 delete_handle (handle_list *hl)
164 {
165   handle_list *hnuke = hl->next;
166   debug_printf ("nuking handle '%s' (%p)", hnuke->name, hnuke->h);
167   hl->next = hnuke->next;
168   memset (hnuke, 0, sizeof (*hnuke));
169 }
170
171 void
172 debug_fixup_after_fork_exec ()
173 {
174 debug_printf ("BEFORE");
175   /* No lock needed at this point */
176   handle_list *hl;
177   for (hl = &cygheap->debug.starth; hl->next != NULL; /* nothing */)
178     if (hl->next->inherited)
179       hl = hl->next;
180     else
181       delete_handle (hl);       // removes hl->next
182 debug_printf ("AFTER");
183 }
184
185 static bool __stdcall
186 mark_closed (const char *func, int ln, HANDLE h, const char *name, bool force)
187 {
188   handle_list *hl;
189
190   if (!cygheap)
191     return true;
192
193   if ((hl = find_handle (h)) && !force)
194     {
195       hl = hl->next;
196       system_printf ("attempt to close protected handle %s:%d(%s<%p>) winpid %d",
197                      hl->func, hl->ln, hl->name, hl->h, hl->pid);
198       system_printf (" by %s:%d(%s<%p>)", func, ln, name, h);
199       return false;
200     }
201
202   handle_list *hln;
203   if (hl && (hln = hl->next) && strcmp (name, hln->name) != 0)
204     {
205       system_printf ("closing protected handle %s:%d(%s<%p>)",
206                      hln->func, hln->ln, hln->name, hln->h);
207       system_printf (" by %s:%d(%s<%p>)", func, ln, name, h);
208     }
209
210   if (hl)
211     delete_handle (hl);
212
213   return true;
214 }
215
216 /* Close a known handle.  Complain if !force and closing a known handle or
217    if the name of the handle being closed does not match the registered name. */
218 bool __stdcall
219 close_handle (const char *func, int ln, HANDLE h, const char *name, bool force)
220 {
221   bool ret;
222
223   lock_debug here;
224   if (!mark_closed (func, ln, h, name, force))
225     return false;
226
227   SetHandleInformation (h, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0);
228   ret = CloseHandle (h);
229
230   if (!ret)
231     {
232       system_printf ("CloseHandle(%s<%p>) failed %s:%d, %E", name, h, func, ln);
233       try_to_debug ();
234     }
235   return ret;
236 }
237 #endif /*DEBUGGING*/