(cygthread::detach): Accept a "wait_for_signal" argument.
(cygthread::terminate_thread): New function.
* cygthread.cc (cygthread::stub): Set stack pointer argument.
(cygthread::terminate_thread): New function. Forcibly terminate thread.
(cygthread::detach): Optionally wait for signals and kill thread when signal
arrives.
* exceptions.cc (signal_exit): Set signal_arrived prior to exiting to wake up
anything blocking on signals.
* fhandler.h (fhandler_base::set_r_no_interrupt): Change to accept bool
argument.
(fhandler_pipe::ready_for_read): Declare.
* pipe.cc (pipeargs): New structure.
(read_pipe): New thread stub wrapper for normal pipe read.
(fhandler_pipe::read): Modify to call reader in a cygthread, terminating on
signal, as appropriate.
* select.cc (fhandler_pipe::ready_for_read): Define new function.
+2002-12-10 Christopher Faylor <cgf@redhat.com>
+
+ * cygthread.h (cygthread::stack_ptr): New element.
+ (cygthread::detach): Accept a "wait_for_signal" argument.
+ (cygthread::terminate_thread): New function.
+ * cygthread.cc (cygthread::stub): Set stack pointer argument.
+ (cygthread::terminate_thread): New function. Forcibly terminate
+ thread.
+ (cygthread::detach): Optionally wait for signals and kill thread when
+ signal arrives.
+ * exceptions.cc (signal_exit): Set signal_arrived prior to exiting to
+ wake up anything blocking on signals.
+ * fhandler.h (fhandler_base::set_r_no_interrupt): Change to accept bool
+ argument.
+ (fhandler_pipe::ready_for_read): Declare.
+ * pipe.cc (pipeargs): New structure.
+ (read_pipe): New thread stub wrapper for normal pipe read.
+ (fhandler_pipe::read): Modify to call reader in a cygthread,
+ terminating on signal, as appropriate.
+ * select.cc (fhandler_pipe::ready_for_read): Define new function.
+
2002-12-10 Corinna Vinschen <corinna@vinschen.de>
* net.cc (free_protoent_ptr): Add missing free() for base structure.
2002-12-10 Craig McGeachie <slapdau@yahoo.com.au>
- * netdb.cc (parse_alias_list, parse_services_line)
- (parse_protocol_line): Change strtok calls to strtok_r.
+ * netdb.cc (parse_alias_list): Change strtok calls to strtok_r.
+ (parse_services_line): Ditto.
+ (parse_protocol_line): Ditto.
2002-12-10 Pierre Humblet <pierre.humblet@ieee.org>
* pwdgrp.h (pwdgrp_check::pwdgrp_state): Replace by
pwdgrp_check::isinitializing ().
(pwdgrp_check::isinitializing): Create.
- * passwd.cc (grab_int): Change type to unsigned, use strtoul and
- set the pointer content to 0 if the field is invalid.
+ * passwd.cc (grab_int): Change type to unsigned, use strtoul and set
+ the pointer content to 0 if the field is invalid.
(parse_pwd): Move validity test after getting pw_gid.
(read_etc_passwd): Replace "passwd_state <= " by
passwd_state::isinitializing ().
(internal_getpwnam): Ditto.
(getpwent): Ditto.
(getpass): Ditto.
- * grp.cc (parse_grp): Use strtoul for gr_gid and verify the validity.
+ * grp.cc (parse_grp): Use strtoul for gr_gid and verify the validity.
(read_etc_group): Replace "group_state <= " by
group_state::isinitializing ().
(internal_getgrgid): Ditto.
#include "winsup.h"
#include <windows.h>
#include <stdlib.h>
+#include <errno.h>
#include "exceptions.h"
#include "security.h"
#include "cygthread.h"
#include "sync.h"
+#include "cygerrno.h"
+#include "sigproc.h"
#undef CloseHandle
-static cygthread NO_COPY threads[9];
+static cygthread NO_COPY threads[18];
#define NTHREADS (sizeof (threads) / sizeof (threads[0]))
DWORD NO_COPY cygthread::main_thread_id;
cygthread *info = (cygthread *) arg;
if (info->arg == cygself)
- info->ev = info->thread_sync = NULL;
+ info->ev = info->thread_sync = info->stack_ptr = NULL;
else
{
info->ev = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
info->thread_sync = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
+ info->stack_ptr = &arg;
}
while (1)
{
ExitThread (0);
}
+/* Forcibly terminate a thread. */
+void
+cygthread::terminate_thread ()
+{
+ if (!is_freerange)
+ SetEvent (*this);
+ (void) TerminateThread (h, 0);
+ (void) WaitForSingleObject (h, INFINITE);
+
+ MEMORY_BASIC_INFORMATION m;
+ memset (&m, 0, sizeof (m));
+ (void) VirtualQuery (stack_ptr, &m, sizeof m);
+
+ if (m.RegionSize)
+ (void) VirtualFree (m.AllocationBase, m.RegionSize, MEM_DECOMMIT);
+
+ if (is_freerange)
+ is_freerange = false;
+ else
+ {
+ CloseHandle (ev);
+ CloseHandle (thread_sync);
+ }
+ CloseHandle (h);
+ thread_sync = ev = h = NULL;
+ __name = NULL;
+ id = 0;
+}
+
/* Detach the cygthread from the current thread. Note that the
theory is that cygthreads are only associated with one thread.
So, there should be no problems with multiple threads doing waits
on the one cygthread. */
void
-cygthread::detach ()
+cygthread::detach (bool wait_for_sig)
{
if (avail)
system_printf ("called detach on available thread %d?", avail);
else
{
DWORD avail = id;
- DWORD res = WaitForSingleObject (*this, INFINITE);
- thread_printf ("WFSO returns %d, id %p", res, id);
+ DWORD res;
+
+ if (!wait_for_sig)
+ res = WaitForSingleObject (*this, INFINITE);
+ else
+ {
+ HANDLE w4[2];
+ w4[0] = signal_arrived;
+ w4[1] = *this;
+ res = WaitForMultipleObjects (2, w4, FALSE, INFINITE);
+ if (res == WAIT_OBJECT_0)
+ {
+ terminate_thread ();
+ set_errno (EINTR); /* caller should be dealing with return
+ values. */
+ avail = 0;
+ }
+ }
+
+ thread_printf ("%s returns %d, id %p", wait_for_sig ? "WFMO" : "WFSO",
+ res, id);
- if (is_freerange)
+ if (!avail)
+ /* already handled */;
+ else if (is_freerange)
{
CloseHandle (h);
free (this);
HANDLE h;
HANDLE ev;
HANDLE thread_sync;
+ void *stack_ptr;
const char *__name;
LPTHREAD_START_ROUTINE func;
VOID *arg;
cygthread (LPTHREAD_START_ROUTINE, LPVOID, const char *);
cygthread () {};
static void init ();
- void detach ();
+ void detach (bool = false);
operator HANDLE ();
static bool is ();
void * operator new (size_t);
static cygthread *freerange ();
void exit_thread ();
+ void terminate_thread ();
static void terminate ();
bool SetThreadPriority (int nPriority) {return ::SetThreadPriority (h, nPriority);}
void zap_h ()
TerminateProcess (hExeced, rc);
sigproc_printf ("about to call do_exit (%x)", rc);
+ (void) SetEvent (signal_arrived);
do_exit (rc);
}
int get_default_fmode (int flags);
bool get_r_no_interrupt () { return FHISSETF (NOEINTR); }
- void set_r_no_interrupt (int b) { FHCONDSETF (b, NOEINTR); }
+ void set_r_no_interrupt (bool b) { FHCONDSETF (b, NOEINTR); }
bool get_close_on_exec () { return FHISSETF (CLOEXEC); }
int set_close_on_exec_flag (int b) { return FHCONDSETF (b, CLOEXEC); }
void set_eof () {broken_pipe = true;}
friend int make_pipe (int fildes[2], unsigned int psize, int mode);
HANDLE get_guard () const {return guard;}
+ int ready_for_read (int fd, DWORD howlong);
};
class fhandler_dev_raw: public fhandler_base
#include "cygheap.h"
#include "thread.h"
#include "pinfo.h"
+#include "cygthread.h"
static unsigned pipecount;
static const NO_COPY char pipeid_fmt[] = "stupid_pipe.%u.%u";
set_inheritance (writepipe_exists, val);
}
+struct pipeargs
+{
+ fhandler_base *fh;
+ void *ptr;
+ size_t len;
+ int res;
+};
+
+static DWORD WINAPI
+read_pipe (void *arg)
+{
+ pipeargs *pi = (pipeargs *) arg;
+ pi->res = pi->fh->fhandler_base::read (pi->ptr, pi->len);
+ return 0;
+}
+
int __stdcall
fhandler_pipe::read (void *in_ptr, size_t in_len)
{
if (broken_pipe)
return 0;
- int res = this->fhandler_base::read (in_ptr, in_len);
+ pipeargs pi;
+ pi.fh = this;
+ pi.ptr = in_ptr;
+ pi.len = in_len;
+ pi.res = -1;
+ cygthread *th = new cygthread (read_pipe, &pi, "read_pipe");
+ th->detach (1);
(void) ReleaseMutex (guard);
- return res;
+ return pi.res;
}
int fhandler_pipe::close ()
{
case FH_PTYM:
case FH_TTYM:
- if (((fhandler_pty_master *)fh)->need_nl)
+ if (((fhandler_pty_master *) fh)->need_nl)
{
gotone = s->read_ready = true;
goto out;
static DWORD WINAPI
thread_pipe (void *arg)
{
- pipeinf *pi = (pipeinf *)arg;
+ pipeinf *pi = (pipeinf *) arg;
BOOL gotone = FALSE;
for (;;)
pipeinf *pi = new pipeinf;
pi->start = &stuff->start;
pi->stop_thread_pipe = FALSE;
- pi->thread = new cygthread (thread_pipe, (LPVOID)pi, "select_pipe");
+ pi->thread = new cygthread (thread_pipe, (LPVOID) pi, "select_pipe");
me->h = *pi->thread;
if (!me->h)
return 0;
- stuff->device_specific[FHDEVN (FH_PIPE)] = (void *)pi;
+ stuff->device_specific[FHDEVN (FH_PIPE)] = (void *) pi;
return 1;
}
static void
pipe_cleanup (select_record *, select_stuff *stuff)
{
- pipeinf *pi = (pipeinf *)stuff->device_specific[FHDEVN (FH_PIPE)];
+ pipeinf *pi = (pipeinf *) stuff->device_specific[FHDEVN (FH_PIPE)];
if (pi && pi->thread)
{
pi->stop_thread_pipe = true;
}
}
+int
+fhandler_pipe::ready_for_read (int fd, DWORD howlong)
+{
+ if (!howlong)
+ return this->fhandler_base::ready_for_read (fd, howlong);
+
+ get_guard ();
+ return true;
+}
+
select_record *
fhandler_pipe::select_read (select_record *s)
{
peek_console (select_record *me, bool)
{
extern const char * get_nonascii_key (INPUT_RECORD& input_rec, char *);
- fhandler_console *fh = (fhandler_console *)me->fh;
+ fhandler_console *fh = (fhandler_console *) me->fh;
if (!me->read_selected)
return me->write_ready;
select_record *
fhandler_tty_common::select_read (select_record *s)
{
- return ((fhandler_pipe*)this)->fhandler_pipe::select_read (s);
+ return ((fhandler_pipe *) this)->fhandler_pipe::select_read (s);
}
select_record *
fhandler_tty_common::select_write (select_record *s)
{
- return ((fhandler_pipe *)this)->fhandler_pipe::select_write (s);
+ return ((fhandler_pipe *) this)->fhandler_pipe::select_write (s);
}
select_record *
fhandler_tty_common::select_except (select_record *s)
{
- return ((fhandler_pipe *)this)->fhandler_pipe::select_except (s);
+ return ((fhandler_pipe *) this)->fhandler_pipe::select_except (s);
}
static int
{
COMSTAT st;
- fhandler_serial *fh = (fhandler_serial *)s->fh;
+ fhandler_serial *fh = (fhandler_serial *) s->fh;
if (fh->get_readahead_valid () || fh->overlapped_armed < 0)
return s->read_ready = true;
static DWORD WINAPI
thread_serial (void *arg)
{
- serialinf *si = (serialinf *)arg;
+ serialinf *si = (serialinf *) arg;
BOOL gotone= FALSE;
for (;;)
serialinf *si = new serialinf;
si->start = &stuff->start;
si->stop_thread_serial = FALSE;
- si->thread = new cygthread (thread_serial, (LPVOID)si, "select_serial");
+ si->thread = new cygthread (thread_serial, (LPVOID) si, "select_serial");
me->h = *si->thread;
- stuff->device_specific[FHDEVN (FH_SERIAL)] = (void *)si;
+ stuff->device_specific[FHDEVN (FH_SERIAL)] = (void *) si;
return 1;
}
static void
serial_cleanup (select_record *, select_stuff *stuff)
{
- serialinf *si = (serialinf *)stuff->device_specific[FHDEVN (FH_SERIAL)];
+ serialinf *si = (serialinf *) stuff->device_specific[FHDEVN (FH_SERIAL)];
if (si && si->thread)
{
si->stop_thread_serial = true;
static DWORD WINAPI
thread_socket (void *arg)
{
- socketinf *si = (socketinf *)arg;
+ socketinf *si = (socketinf *) arg;
select_printf ("stuff_start %p", &si->start);
int r = WINSOCK_SELECT (0, &si->readfds, &si->writefds, &si->exceptfds, NULL);
{
socketinf *si;
- if ((si = (socketinf *)stuff->device_specific[FHDEVN (FH_SOCKET)]))
+ if ((si = (socketinf *) stuff->device_specific[FHDEVN (FH_SOCKET)]))
{
me->h = *si->thread;
return 1;
stuff->device_specific[FHDEVN (FH_SOCKET)] = (void *) si;
si->start = &stuff->start;
select_printf ("stuff_start %p", &stuff->start);
- si->thread = new cygthread (thread_socket, (LPVOID)si, "select_socket");
+ si->thread = new cygthread (thread_socket, (LPVOID) si, "select_socket");
me->h = *si->thread;
return 1;
void
socket_cleanup (select_record *, select_stuff *stuff)
{
- socketinf *si = (socketinf *)stuff->device_specific[FHDEVN (FH_SOCKET)];
+ socketinf *si = (socketinf *) stuff->device_specific[FHDEVN (FH_SOCKET)];
select_printf ("si %p si->thread %p", si, si ? si->thread : NULL);
if (si && si->thread)
{