Mail Archives: cygwin-developers/1999/12/06/22:52:12
Completely forgot about the synchronization used in makethread to avoid
stack corruption, and that's why enabling signals for dynamically loaded
Cygwin was crashing in newly created threads.
This change removes the synchronization and uses dynamically allocated
memory to the thread stub routine, which frees the memory. The overhead
should be roughly the same, perhaps a tiny bit higher due to malloc's
internal MT synchronization.
A gotcha for future users of makethread -- if you pass a thread parameter,
make sure it's not on the stack (which is the case currently, so it should
be safe).
Patch against today's snapshot.
Mon Dec 6 21:32:01 1999 Mumit Khan <khan AT xraylith DOT wisc DOT edu>
* dcrt0.cc (dll_crt0_1): Enable signal handling for dynamically
loaded case.
* debug.cc: Include stdlib.h.
(thread_start): Delete sync field.
(thread_stub): Remove use of thread_start.sync field, and free
the memory for the argument.
(makethread): Dynamically allocate the argument passed to
thread_stub, and remove synchronization.
Index: dcrt0.cc
===================================================================
RCS file: /home/khan/CVSROOT/cygwin/winsup/dcrt0.cc,v
retrieving revision 1.1.1.2
diff -u -3 -p -r1.1.1.2 dcrt0.cc
--- dcrt0.cc 1999/12/07 01:36:15 1.1.1.2
+++ dcrt0.cc 1999/12/07 02:43:28
@@ -713,13 +713,8 @@ dll_crt0_1 ()
/* Allocate dtable */
dtable_init ();
- /* Can't use signals in non-cygwin apps since it depends on synchronizing
- with a a helper thread. */
- if (!dynamically_loaded)
- {
- /* Initialize signal/subprocess handling. */
- sigproc_init ();
- }
+ /* Initialize signal/subprocess handling. */
+ sigproc_init ();
/* Connect to tty. */
tty_init ();
Index: debug.cc
===================================================================
RCS file: /home/khan/CVSROOT/cygwin/winsup/debug.cc,v
retrieving revision 1.1.1.2
diff -u -3 -p -r1.1.1.2 debug.cc
--- debug.cc 1999/12/07 01:36:15 1.1.1.2
+++ debug.cc 1999/12/07 02:51:22
@@ -9,6 +9,7 @@ details. */
#define NO_DEBUG_DEFINES
#include "winsup.h"
#include "exceptions.h"
+#include <stdlib.h>
static muto NO_COPY *__tn = NULL;
#define lock_thread_name() \
@@ -27,7 +28,6 @@ typedef struct
{
LPTHREAD_START_ROUTINE func;
VOID *arg;
- HANDLE sync;
} thread_start;
static NO_COPY thread_info threads[32]; // increase as necessary
@@ -72,9 +72,7 @@ thread_stub (VOID *arg)
api_fatal(" Sig proc MT init failed\n");
#endif
- /* Signal the initiating thread that we've copied 'info' here and that it's
- safe to continue. */
- SetEvent (info.sync);
+ free (arg);
init_exceptions (&except_entry);
@@ -90,18 +88,18 @@ makethread (LPTHREAD_START_ROUTINE start
DWORD tid;
HANDLE h;
SECURITY_ATTRIBUTES *sa;
- thread_start info; /* Various information needed by the newly created thread */
+ /* Various information needed by the newly created thread. The memory
+ is released by thread_stub. */
+ thread_start* info = (thread_start *) malloc (sizeof (thread_start));
- info.func = start; /* Real function to start */
- info.arg = param; /* The single parameter to the thread */
+ if (!info)
+ {
+ debug_printf ("malloc failed, %E");
+ return INVALID_HANDLE_VALUE;
+ }
- /* This event is used to synchronize with the newly created thread. It ensures
- that this function will not exit before the 'info' information above is copied
- to the thread's stack from *this* thread's stack.
-
- Without this synchronization, this function would just continue and the stack
- for makethread could be overwritten before the thread_stub gets to it. */
- info.sync = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
+ info->func = start; /* Real function to start */
+ info->arg = param; /* The single parameter to the thread */
if (*name != '+')
sa = &sec_none_nih; /* The handle should not be inherited by subprocesses. */
@@ -111,13 +109,10 @@ makethread (LPTHREAD_START_ROUTINE start
sa = &sec_none; /* The handle should be inherited by subprocesses. */
}
- if ((h = CreateThread (sa, 0, thread_stub, (VOID *)&info, flags, &tid)))
+ if ((h = CreateThread (sa, 0, thread_stub, (VOID *)info, flags, &tid)))
{
regthread (name, tid); /* Register this name/thread id for debugging output. */
- WaitForSingleObject (info.sync, INFINITE); /* Wait for go ahead from the new thread. */
}
- CloseHandle (info.sync);
-
return h;
}
- Raw text -