3 Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red
6 This software is a copyrighted work licensed under the terms of the
7 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 #define USE_SYS_TYPES_FD_SET
20 #include "exception.h"
22 /* Two calls to get the stack right... */
24 _cygtls::call (DWORD (*func
) (void *, void *), void *arg
)
26 char buf
[CYGTLS_PADSIZE
];
27 /* Initialize this thread's ability to respond to things like
30 _my_tls
.call2 (func
, arg
, buf
);
34 dll_cmp (const void *a
, const void *b
)
36 return wcscasecmp ((const wchar_t *) a
, *(const wchar_t **) b
);
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
45 const wchar_t *well_known_dlls
[] =
58 _cygtls::call2 (DWORD (*func
) (void *, void *), void *arg
, void *buf
)
60 init_thread (buf
, func
);
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,
64 since pthreads are always calling thread_wrapper in miscfuncs.cc.
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.
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
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
))
84 MEMORY_BASIC_INFORMATION mbi
;
85 wchar_t modname
[PATH_MAX
];
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
);
99 DWORD res
= func (arg
, buf
);
101 /* Don't call ExitThread on the main thread since we may have been
102 dynamically loaded. */
103 if ((void *) func
!= (void *) dll_crt0_1
104 && (void *) func
!= (void *) dll_dllcrt0_1
)
109 _cygtls::init_thread (void *x
, DWORD (*func
) (void *, void *))
113 memset (this, 0, sizeof (*this));
114 _REENT_INIT_PTR (&local_clib
);
118 local_clib
._stdin
= _GLOBAL_REENT
->_stdin
;
119 local_clib
._stdout
= _GLOBAL_REENT
->_stdout
;
120 local_clib
._stderr
= _GLOBAL_REENT
->_stderr
;
121 local_clib
.__sdidinit
= _GLOBAL_REENT
->__sdidinit
? -1 : 0;
122 local_clib
.__cleanup
= _GLOBAL_REENT
->__cleanup
;
123 local_clib
.__sglue
._niobs
= 3;
124 local_clib
.__sglue
._iobs
= &_GLOBAL_REENT
->__sf
[0];
128 thread_id
= GetCurrentThreadId ();
129 initialized
= CYGTLS_INITIALIZED
;
130 errno_addr
= &(local_clib
._errno
);
131 locals
.cw_timer
= NULL
;
133 if ((void *) func
== (void *) cygthread::stub
134 || (void *) func
== (void *) cygthread::simplestub
)
137 cygheap
->add_tls (this);
141 _cygtls::fixup_after_fork ()
148 stacklock
= spinning
= 0;
149 signal_arrived
= NULL
;
150 locals
.select
.sockevt
= NULL
;
151 locals
.cw_timer
= NULL
;
155 #define free_local(x) \
163 _cygtls::remove (DWORD wait
)
166 if (exit_state
>= ES_FINAL
)
169 debug_printf ("wait %p", wait
);
171 /* FIXME: Need some sort of atthreadexit function to allow things like
172 select to control this themselves. */
176 HANDLE h
= signal_arrived
;
177 signal_arrived
= NULL
;
181 /* Close handle and free memory used by select. */
182 if (locals
.select
.sockevt
)
184 CloseHandle (locals
.select
.sockevt
);
185 locals
.select
.sockevt
= NULL
;
186 free_local (select
.ser_num
);
187 free_local (select
.w4
);
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
);
194 /* Free temporary TLS path buffers. */
195 locals
.pathbufs
.destroy ();
196 cygheap
->remove_tls (this, wait
);