Cygwin: strptime: add release note
[newlib-cygwin.git] / winsup / cygwin / debug.cc
blob050ffd9dc7e97d8c4a5e47ab44618e6f0513f080
1 /* debug.cc
3 This software is a copyrighted work licensed under the terms of the
4 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
5 details. */
7 #include "winsup.h"
8 #include "cygerrno.h"
9 #ifdef DEBUGGING
10 #include "path.h"
11 #include "fhandler.h"
12 #include "dtable.h"
13 #include "cygheap.h"
14 #endif
16 #undef CloseHandle
18 #ifdef DEBUGGING
19 /* Here lies extra debugging routines which help track down internal
20 Cygwin problems when compiled with -DDEBUGGING . */
21 #define NFREEH (sizeof (cygheap->debug.freeh) / sizeof (cygheap->debug.freeh[0]))
23 class lock_debug
25 static NO_COPY SRWLOCK lock;
26 public:
27 lock_debug () { AcquireSRWLockExclusive (&lock); }
28 ~lock_debug () { ReleaseSRWLockExclusive (&lock); }
31 SRWLOCK NO_COPY lock_debug::lock = SRWLOCK_INIT;
33 static bool mark_closed (const char *, int, HANDLE, const char *, bool);
35 /* Find a registered handle in the linked list of handles. */
36 static handle_list *
37 find_handle (HANDLE h)
39 handle_list *hl;
40 for (hl = &cygheap->debug.starth; hl->next != NULL; hl = hl->next)
41 if (hl->next->h == h)
42 goto out;
43 hl = NULL;
45 out:
46 return hl;
49 void
50 verify_handle (const char *func, int ln, HANDLE h)
52 lock_debug here;
53 handle_list *hl = find_handle (h);
54 if (!hl)
55 return;
56 system_printf ("%s:%d - multiple attempts to add handle %p", func, ln, h);
58 system_printf (" previously allocated by %s:%d(%s<%p>) winpid %d",
59 hl->func, hl->ln, hl->name, hl->h, hl->pid);
62 void
63 setclexec (HANDLE oh, HANDLE nh, bool not_inheriting)
65 lock_debug here;
66 handle_list *hl = find_handle (oh);
67 if (hl)
69 hl = hl->next;
70 hl->inherited = !not_inheriting;
71 hl->h = nh;
75 /* Create a new handle record */
76 static handle_list *
77 newh ()
79 handle_list *hl;
81 for (hl = cygheap->debug.freeh; hl < cygheap->debug.freeh + NFREEH; hl++)
82 if (hl->name == NULL)
83 return hl;
85 return NULL;
88 void
89 modify_handle (const char *func, int ln, HANDLE h, const char *name, bool inh)
91 lock_debug here;
92 handle_list *hl = find_handle (h);
93 if (!hl)
95 system_printf ("%s:%d handle %s<%p> not found", func, ln, name, h);
96 return;
98 hl->next->inherited = inh;
99 debug_printf ("%s:%d set handle %s<%p> inheritance flag to %d", func, ln,
100 name, h, inh);
103 /* Add a handle to the linked list of known handles. */
104 void
105 add_handle (const char *func, int ln, HANDLE h, const char *name, bool inh)
107 handle_list *hl;
109 if (!cygheap)
110 return;
112 lock_debug here;
113 if ((hl = find_handle (h)))
115 hl = hl->next;
116 if (hl->name == name && hl->func == func && hl->ln == ln)
117 return;
118 system_printf ("%s:%d - multiple attempts to add handle %s<%p>", func,
119 ln, name, h);
120 system_printf (" previously allocated by %s:%d(%s<%p>) winpid %d",
121 hl->func, hl->ln, hl->name, hl->h, hl->pid);
122 return;
125 if ((hl = newh ()) == NULL)
127 debug_printf ("couldn't allocate memory for %s(%d): %s(%p)",
128 func, ln, name, h);
129 return;
131 hl->h = h;
132 hl->name = name;
133 hl->func = func;
134 hl->ln = ln;
135 hl->inherited = inh;
136 hl->pid = GetCurrentProcessId ();
137 hl->next = cygheap->debug.starth.next;
138 cygheap->debug.starth.next = hl;
139 SetHandleInformation (h, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE);
140 debug_printf ("protecting handle '%s'(%p), inherited flag %d", hl->name, hl->h, hl->inherited);
143 static void
144 delete_handle (handle_list *hl)
146 handle_list *hnuke = hl->next;
147 debug_printf ("nuking handle '%s' (%p)", hnuke->name, hnuke->h);
148 hl->next = hnuke->next;
149 memset (hnuke, 0, sizeof (*hnuke));
152 void
153 debug_fixup_after_fork_exec ()
155 /* No lock needed at this point */
156 handle_list *hl;
157 for (hl = &cygheap->debug.starth; hl->next != NULL; /* nothing */)
158 if (hl->next->inherited)
159 hl = hl->next;
160 else
161 delete_handle (hl); // removes hl->next
164 static bool
165 mark_closed (const char *func, int ln, HANDLE h, const char *name, bool force)
167 handle_list *hl;
169 if (!cygheap)
170 return true;
172 if ((hl = find_handle (h)) && !force)
174 hl = hl->next;
175 system_printf ("attempt to close protected handle %s:%d(%s<%p>) winpid %d",
176 hl->func, hl->ln, hl->name, hl->h, hl->pid);
177 system_printf (" by %s:%d(%s<%p>)", func, ln, name, h);
178 return false;
181 handle_list *hln;
182 if (hl && (hln = hl->next) && strcmp (name, hln->name) != 0)
184 system_printf ("closing protected handle %s:%d(%s<%p>)",
185 hln->func, hln->ln, hln->name, hln->h);
186 system_printf (" by %s:%d(%s<%p>)", func, ln, name, h);
189 if (hl)
190 delete_handle (hl);
192 return true;
195 /* Close a known handle. Complain if !force and closing a known handle or
196 if the name of the handle being closed does not match the registered name. */
197 bool
198 close_handle (const char *func, int ln, HANDLE h, const char *name, bool force)
200 bool ret;
202 lock_debug here;
203 if (!mark_closed (func, ln, h, name, force))
204 return false;
206 SetHandleInformation (h, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0);
207 ret = CloseHandle (h);
209 if (!ret)
211 system_printf ("CloseHandle(%s<%p>) failed %s:%d, %E", name, h, func, ln);
212 try_to_debug ();
214 return ret;
216 #endif /*DEBUGGING*/