]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/cygtls.cc
* Merge in cygwin-64bit-branch.
[newlib-cygwin.git] / winsup / cygwin / cygtls.cc
CommitLineData
2d1d1eb1 1/* cygtls.cc
281e4194 2
bc837d22
CF
3 Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red
4 Hat, Inc.
281e4194
CF
5
6This software is a copyrighted work licensed under the terms of the
7Cygwin license. Please consult the file "CYGWIN_LICENSE" for
8details. */
9
10#include "winsup.h"
893ac8e0 11#define USE_SYS_TYPES_FD_SET
281e4194 12#include "cygtls.h"
281e4194 13#include <syslog.h>
2be50cac 14#include <stdlib.h>
2d1d1eb1
CF
15#include "path.h"
16#include "fhandler.h"
17#include "dtable.h"
18#include "cygheap.h"
f6936c48 19#include "sigproc.h"
98a97ac6 20#include "exception.h"
2d1d1eb1 21
281e4194
CF
22/* Two calls to get the stack right... */
23void
e431827c 24_cygtls::call (DWORD (*func) (void *, void *), void *arg)
281e4194
CF
25{
26 char buf[CYGTLS_PADSIZE];
98a97ac6
CF
27 /* Initialize this thread's ability to respond to things like
28 SIGSEGV or SIGFPE. */
29 exception protect;
38229bcd 30 _my_tls.call2 (func, arg, buf);
281e4194
CF
31}
32
07a6b9dd
CV
33static int
34dll_cmp (const void *a, const void *b)
35{
36 return wcscasecmp ((const wchar_t *) a, *(const wchar_t **) b);
37}
38
39/* Keep sorted!
40 This is a list of well-known core system DLLs which contain code
41 whiuch is started in its own thread by the system. Kernel32.dll,
42 for instance, contains the thread called on every Ctrl-C keypress
43 in a console window. The DLLs in this list are not recognized as
44 BLODAs. */
45const wchar_t *well_known_dlls[] =
46{
5a519b88 47 L"advapi32.dll",
07a6b9dd
CV
48 L"kernel32.dll",
49 L"mswsock.dll",
50 L"ntdll.dll",
4a4f6f94 51 L"ole32.dll",
d783d46c 52 L"shlwapi.dll",
4a4f6f94 53 L"wbemprox.dll",
07a6b9dd
CV
54 L"ws2_32.dll",
55};
56
281e4194 57void
e431827c 58_cygtls::call2 (DWORD (*func) (void *, void *), void *arg, void *buf)
281e4194 59{
38229bcd 60 init_thread (buf, func);
07a6b9dd
CV
61
62 /* Optional BLODA detection. The idea is that the function address is
63 supposed to be within Cygwin itself. This is also true for pthreads,
46f5dd59 64 since pthreads are always calling thread_wrapper in miscfuncs.cc.
07a6b9dd
CV
65 Therefore, every function call to a function outside of the Cygwin DLL
66 is potentially a thread injected into the Cygwin process by some BLODA.
67
68 But that's a bit too simple. Assuming the application itself calls
69 CreateThread, then this is a bad idea, but not really invalid. So we
70 shouldn't print a BLODA message if the address is within the loaded
71 image of the application. Also, ntdll.dll starts threads into the
72 application which */
73 if (detect_bloda)
74 {
75 PIMAGE_DOS_HEADER img_start = (PIMAGE_DOS_HEADER) GetModuleHandle (NULL);
76 PIMAGE_NT_HEADERS32 ntheader = (PIMAGE_NT_HEADERS32)
77 ((PBYTE) img_start + img_start->e_lfanew);
78 void *img_end = (void *) ((PBYTE) img_start
79 + ntheader->OptionalHeader.SizeOfImage);
80 if (((void *) func < (void *) cygwin_hmodule
81 || (void *) func > (void *) cygheap)
82 && ((void *) func < (void *) img_start || (void *) func >= img_end))
83 {
84 MEMORY_BASIC_INFORMATION mbi;
85 wchar_t modname[PATH_MAX];
86
87 VirtualQuery ((PVOID) func, &mbi, sizeof mbi);
88 GetModuleFileNameW ((HMODULE) mbi.AllocationBase, modname, PATH_MAX);
89 /* Fetch basename and check against list of above system DLLs. */
90 const wchar_t *modbasename = wcsrchr (modname, L'\\') + 1;
91 if (!bsearch (modbasename, well_known_dlls,
92 sizeof well_known_dlls / sizeof well_known_dlls[0],
93 sizeof well_known_dlls[0], dll_cmp))
94 small_printf ("\n\nPotential BLODA detected! Thread function "
95 "called outside of Cygwin DLL:\n %W\n\n", modname);
96 }
97 }
98
2d1d1eb1 99 DWORD res = func (arg, buf);
38229bcd 100 remove (INFINITE);
a2b6c065
CF
101 /* Don't call ExitThread on the main thread since we may have been
102 dynamically loaded. */
2346864a
CF
103 if ((void *) func != (void *) dll_crt0_1
104 && (void *) func != (void *) dll_dllcrt0_1)
65068ebd 105 ExitThread (res);
281e4194
CF
106}
107
108void
e431827c 109_cygtls::init_thread (void *x, DWORD (*func) (void *, void *))
281e4194
CF
110{
111 if (x)
112 {
562adf78 113 memset (this, 0, sizeof (*this));
cd441f06 114 _REENT_INIT_PTR (&local_clib);
281e4194
CF
115 stackptr = stack;
116 if (_GLOBAL_REENT)
117 {
118 local_clib._stdin = _GLOBAL_REENT->_stdin;
119 local_clib._stdout = _GLOBAL_REENT->_stdout;
120 local_clib._stderr = _GLOBAL_REENT->_stderr;
6f7a746c 121 local_clib.__sdidinit = _GLOBAL_REENT->__sdidinit ? -1 : 0;
281e4194 122 local_clib.__cleanup = _GLOBAL_REENT->__cleanup;
5e0f482f
CF
123 local_clib.__sglue._niobs = 3;
124 local_clib.__sglue._iobs = &_GLOBAL_REENT->__sf[0];
281e4194 125 }
281e4194
CF
126 }
127
985d0e68 128 thread_id = GetCurrentThreadId ();
09b01096 129 initialized = CYGTLS_INITIALIZED;
281e4194 130 errno_addr = &(local_clib._errno);
f0968c1e 131 locals.cw_timer = NULL;
2d1d1eb1
CF
132
133 if ((void *) func == (void *) cygthread::stub
134 || (void *) func == (void *) cygthread::simplestub)
135 return;
136
52d2371d 137 cygheap->add_tls (this);
281e4194
CF
138}
139
140void
e431827c
CF
141_cygtls::fixup_after_fork ()
142{
e867f8f1
CF
143 if (sig)
144 {
145 pop ();
146 sig = 0;
147 }
82c925af 148 stacklock = spinning = 0;
962f9a2c 149 signal_arrived = NULL;
023c2582 150 locals.select.sockevt = NULL;
f0968c1e 151 locals.cw_timer = NULL;
9863b78e 152 wq.thread_ev = NULL;
e431827c
CF
153}
154
fe836470
CF
155#define free_local(x) \
156 if (locals.x) \
157 { \
158 free (locals.x); \
159 locals.x = NULL; \
160 }
161
e431827c
CF
162void
163_cygtls::remove (DWORD wait)
281e4194 164{
9badd94a 165 initialized = 0;
023c2582 166 if (exit_state >= ES_FINAL)
55b67002 167 return;
4cf4fd4d 168
61522196 169 debug_printf ("wait %u", wait);
a0307f99
CV
170
171 /* FIXME: Need some sort of atthreadexit function to allow things like
172 select to control this themselves. */
173
962f9a2c
CF
174 if (signal_arrived)
175 {
176 HANDLE h = signal_arrived;
177 signal_arrived = NULL;
178 CloseHandle (h);
179 }
180
a0307f99 181 /* Close handle and free memory used by select. */
1d8170bd 182 if (locals.select.sockevt)
42aa06a5 183 {
a0307f99
CV
184 CloseHandle (locals.select.sockevt);
185 locals.select.sockevt = NULL;
186 free_local (select.ser_num);
187 free_local (select.w4);
42aa06a5 188 }
a0307f99
CV
189 /* Free memory used by network functions. */
190 free_local (ntoa_buf);
191 free_local (protoent_buf);
192 free_local (servent_buf);
193 free_local (hostent_buf);
752b16ce
CV
194 /* Free temporary TLS path buffers. */
195 locals.pathbufs.destroy ();
52d2371d 196 cygheap->remove_tls (this, wait);
168d7785 197 remove_wq (wait);
281e4194 198}
This page took 0.273072 seconds and 5 git commands to generate.