* 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.
This commit is contained in:
Christopher Faylor 2002-12-11 04:00:04 +00:00
parent ea01c7f5d2
commit 1d380f593a
7 changed files with 146 additions and 33 deletions

View File

@ -1,3 +1,24 @@
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> 2002-12-10 Corinna Vinschen <corinna@vinschen.de>
* net.cc (free_protoent_ptr): Add missing free() for base structure. * net.cc (free_protoent_ptr): Add missing free() for base structure.
@ -6,16 +27,17 @@
2002-12-10 Craig McGeachie <slapdau@yahoo.com.au> 2002-12-10 Craig McGeachie <slapdau@yahoo.com.au>
* netdb.cc (parse_alias_list, parse_services_line) * netdb.cc (parse_alias_list): Change strtok calls to strtok_r.
(parse_protocol_line): Change strtok calls to strtok_r. (parse_services_line): Ditto.
(parse_protocol_line): Ditto.
2002-12-10 Pierre Humblet <pierre.humblet@ieee.org> 2002-12-10 Pierre Humblet <pierre.humblet@ieee.org>
* pwdgrp.h (pwdgrp_check::pwdgrp_state): Replace by * pwdgrp.h (pwdgrp_check::pwdgrp_state): Replace by
pwdgrp_check::isinitializing (). pwdgrp_check::isinitializing ().
(pwdgrp_check::isinitializing): Create. (pwdgrp_check::isinitializing): Create.
* passwd.cc (grab_int): Change type to unsigned, use strtoul and * passwd.cc (grab_int): Change type to unsigned, use strtoul and set
set the pointer content to 0 if the field is invalid. the pointer content to 0 if the field is invalid.
(parse_pwd): Move validity test after getting pw_gid. (parse_pwd): Move validity test after getting pw_gid.
(read_etc_passwd): Replace "passwd_state <= " by (read_etc_passwd): Replace "passwd_state <= " by
passwd_state::isinitializing (). passwd_state::isinitializing ().
@ -23,7 +45,7 @@
(internal_getpwnam): Ditto. (internal_getpwnam): Ditto.
(getpwent): Ditto. (getpwent): Ditto.
(getpass): 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 (read_etc_group): Replace "group_state <= " by
group_state::isinitializing (). group_state::isinitializing ().
(internal_getgrgid): Ditto. (internal_getgrgid): Ditto.

View File

@ -9,14 +9,17 @@ details. */
#include "winsup.h" #include "winsup.h"
#include <windows.h> #include <windows.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
#include "exceptions.h" #include "exceptions.h"
#include "security.h" #include "security.h"
#include "cygthread.h" #include "cygthread.h"
#include "sync.h" #include "sync.h"
#include "cygerrno.h"
#include "sigproc.h"
#undef CloseHandle #undef CloseHandle
static cygthread NO_COPY threads[9]; static cygthread NO_COPY threads[18];
#define NTHREADS (sizeof (threads) / sizeof (threads[0])) #define NTHREADS (sizeof (threads) / sizeof (threads[0]))
DWORD NO_COPY cygthread::main_thread_id; DWORD NO_COPY cygthread::main_thread_id;
@ -37,11 +40,12 @@ cygthread::stub (VOID *arg)
cygthread *info = (cygthread *) arg; cygthread *info = (cygthread *) arg;
if (info->arg == cygself) if (info->arg == cygself)
info->ev = info->thread_sync = NULL; info->ev = info->thread_sync = info->stack_ptr = NULL;
else else
{ {
info->ev = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); info->ev = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
info->thread_sync = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL); info->thread_sync = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
info->stack_ptr = &arg;
} }
while (1) while (1)
{ {
@ -231,22 +235,72 @@ cygthread::exit_thread ()
ExitThread (0); 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 /* Detach the cygthread from the current thread. Note that the
theory is that cygthreads are only associated with one thread. theory is that cygthreads are only associated with one thread.
So, there should be no problems with multiple threads doing waits So, there should be no problems with multiple threads doing waits
on the one cygthread. */ on the one cygthread. */
void void
cygthread::detach () cygthread::detach (bool wait_for_sig)
{ {
if (avail) if (avail)
system_printf ("called detach on available thread %d?", avail); system_printf ("called detach on available thread %d?", avail);
else else
{ {
DWORD avail = id; DWORD avail = id;
DWORD res = WaitForSingleObject (*this, INFINITE); DWORD res;
thread_printf ("WFSO returns %d, id %p", res, id);
if (is_freerange) 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 (!avail)
/* already handled */;
else if (is_freerange)
{ {
CloseHandle (h); CloseHandle (h);
free (this); free (this);

View File

@ -13,6 +13,7 @@ class cygthread
HANDLE h; HANDLE h;
HANDLE ev; HANDLE ev;
HANDLE thread_sync; HANDLE thread_sync;
void *stack_ptr;
const char *__name; const char *__name;
LPTHREAD_START_ROUTINE func; LPTHREAD_START_ROUTINE func;
VOID *arg; VOID *arg;
@ -26,12 +27,13 @@ class cygthread
cygthread (LPTHREAD_START_ROUTINE, LPVOID, const char *); cygthread (LPTHREAD_START_ROUTINE, LPVOID, const char *);
cygthread () {}; cygthread () {};
static void init (); static void init ();
void detach (); void detach (bool = false);
operator HANDLE (); operator HANDLE ();
static bool is (); static bool is ();
void * operator new (size_t); void * operator new (size_t);
static cygthread *freerange (); static cygthread *freerange ();
void exit_thread (); void exit_thread ();
void terminate_thread ();
static void terminate (); static void terminate ();
bool SetThreadPriority (int nPriority) {return ::SetThreadPriority (h, nPriority);} bool SetThreadPriority (int nPriority) {return ::SetThreadPriority (h, nPriority);}
void zap_h () void zap_h ()

View File

@ -1117,6 +1117,7 @@ signal_exit (int rc)
TerminateProcess (hExeced, rc); TerminateProcess (hExeced, rc);
sigproc_printf ("about to call do_exit (%x)", rc); sigproc_printf ("about to call do_exit (%x)", rc);
(void) SetEvent (signal_arrived);
do_exit (rc); do_exit (rc);
} }

View File

@ -219,7 +219,7 @@ class fhandler_base
int get_default_fmode (int flags); int get_default_fmode (int flags);
bool get_r_no_interrupt () { return FHISSETF (NOEINTR); } 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); } bool get_close_on_exec () { return FHISSETF (CLOEXEC); }
int set_close_on_exec_flag (int b) { return FHCONDSETF (b, CLOEXEC); } int set_close_on_exec_flag (int b) { return FHCONDSETF (b, CLOEXEC); }
@ -473,6 +473,7 @@ class fhandler_pipe: public fhandler_base
void set_eof () {broken_pipe = true;} void set_eof () {broken_pipe = true;}
friend int make_pipe (int fildes[2], unsigned int psize, int mode); friend int make_pipe (int fildes[2], unsigned int psize, int mode);
HANDLE get_guard () const {return guard;} HANDLE get_guard () const {return guard;}
int ready_for_read (int fd, DWORD howlong);
}; };
class fhandler_dev_raw: public fhandler_base class fhandler_dev_raw: public fhandler_base

View File

@ -22,6 +22,7 @@ details. */
#include "cygheap.h" #include "cygheap.h"
#include "thread.h" #include "thread.h"
#include "pinfo.h" #include "pinfo.h"
#include "cygthread.h"
static unsigned pipecount; static unsigned pipecount;
static const NO_COPY char pipeid_fmt[] = "stupid_pipe.%u.%u"; static const NO_COPY char pipeid_fmt[] = "stupid_pipe.%u.%u";
@ -50,14 +51,36 @@ fhandler_pipe::set_close_on_exec (int val)
set_inheritance (writepipe_exists, val); 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 int __stdcall
fhandler_pipe::read (void *in_ptr, size_t in_len) fhandler_pipe::read (void *in_ptr, size_t in_len)
{ {
if (broken_pipe) if (broken_pipe)
return 0; 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); (void) ReleaseMutex (guard);
return res; return pi.res;
} }
int fhandler_pipe::close () int fhandler_pipe::close ()

View File

@ -431,7 +431,7 @@ peek_pipe (select_record *s, bool from_select)
{ {
case FH_PTYM: case FH_PTYM:
case FH_TTYM: case FH_TTYM:
if (((fhandler_pty_master *)fh)->need_nl) if (((fhandler_pty_master *) fh)->need_nl)
{ {
gotone = s->read_ready = true; gotone = s->read_ready = true;
goto out; goto out;
@ -521,7 +521,7 @@ struct pipeinf
static DWORD WINAPI static DWORD WINAPI
thread_pipe (void *arg) thread_pipe (void *arg)
{ {
pipeinf *pi = (pipeinf *)arg; pipeinf *pi = (pipeinf *) arg;
BOOL gotone = FALSE; BOOL gotone = FALSE;
for (;;) for (;;)
@ -563,18 +563,18 @@ start_thread_pipe (select_record *me, select_stuff *stuff)
pipeinf *pi = new pipeinf; pipeinf *pi = new pipeinf;
pi->start = &stuff->start; pi->start = &stuff->start;
pi->stop_thread_pipe = FALSE; 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; me->h = *pi->thread;
if (!me->h) if (!me->h)
return 0; return 0;
stuff->device_specific[FHDEVN (FH_PIPE)] = (void *)pi; stuff->device_specific[FHDEVN (FH_PIPE)] = (void *) pi;
return 1; return 1;
} }
static void static void
pipe_cleanup (select_record *, select_stuff *stuff) 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) if (pi && pi->thread)
{ {
pi->stop_thread_pipe = true; pi->stop_thread_pipe = true;
@ -584,6 +584,16 @@ pipe_cleanup (select_record *, select_stuff *stuff)
} }
} }
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 * select_record *
fhandler_pipe::select_read (select_record *s) fhandler_pipe::select_read (select_record *s)
{ {
@ -631,7 +641,7 @@ static int
peek_console (select_record *me, bool) peek_console (select_record *me, bool)
{ {
extern const char * get_nonascii_key (INPUT_RECORD& input_rec, char *); 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) if (!me->read_selected)
return me->write_ready; return me->write_ready;
@ -748,19 +758,19 @@ fhandler_console::select_except (select_record *s)
select_record * select_record *
fhandler_tty_common::select_read (select_record *s) 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 * select_record *
fhandler_tty_common::select_write (select_record *s) 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 * select_record *
fhandler_tty_common::select_except (select_record *s) 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 static int
@ -846,7 +856,7 @@ peek_serial (select_record *s, bool)
{ {
COMSTAT st; 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) if (fh->get_readahead_valid () || fh->overlapped_armed < 0)
return s->read_ready = true; return s->read_ready = true;
@ -944,7 +954,7 @@ err:
static DWORD WINAPI static DWORD WINAPI
thread_serial (void *arg) thread_serial (void *arg)
{ {
serialinf *si = (serialinf *)arg; serialinf *si = (serialinf *) arg;
BOOL gotone= FALSE; BOOL gotone= FALSE;
for (;;) for (;;)
@ -980,16 +990,16 @@ start_thread_serial (select_record *me, select_stuff *stuff)
serialinf *si = new serialinf; serialinf *si = new serialinf;
si->start = &stuff->start; si->start = &stuff->start;
si->stop_thread_serial = FALSE; 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; me->h = *si->thread;
stuff->device_specific[FHDEVN (FH_SERIAL)] = (void *)si; stuff->device_specific[FHDEVN (FH_SERIAL)] = (void *) si;
return 1; return 1;
} }
static void static void
serial_cleanup (select_record *, select_stuff *stuff) 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) if (si && si->thread)
{ {
si->stop_thread_serial = true; si->stop_thread_serial = true;
@ -1200,7 +1210,7 @@ static int start_thread_socket (select_record *, select_stuff *);
static DWORD WINAPI static DWORD WINAPI
thread_socket (void *arg) thread_socket (void *arg)
{ {
socketinf *si = (socketinf *)arg; socketinf *si = (socketinf *) arg;
select_printf ("stuff_start %p", &si->start); select_printf ("stuff_start %p", &si->start);
int r = WINSOCK_SELECT (0, &si->readfds, &si->writefds, &si->exceptfds, NULL); int r = WINSOCK_SELECT (0, &si->readfds, &si->writefds, &si->exceptfds, NULL);
@ -1243,7 +1253,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
{ {
socketinf *si; socketinf *si;
if ((si = (socketinf *)stuff->device_specific[FHDEVN (FH_SOCKET)])) if ((si = (socketinf *) stuff->device_specific[FHDEVN (FH_SOCKET)]))
{ {
me->h = *si->thread; me->h = *si->thread;
return 1; return 1;
@ -1314,7 +1324,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
stuff->device_specific[FHDEVN (FH_SOCKET)] = (void *) si; stuff->device_specific[FHDEVN (FH_SOCKET)] = (void *) si;
si->start = &stuff->start; si->start = &stuff->start;
select_printf ("stuff_start %p", &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; me->h = *si->thread;
return 1; return 1;
@ -1327,7 +1337,7 @@ err:
void void
socket_cleanup (select_record *, select_stuff *stuff) 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); select_printf ("si %p si->thread %p", si, si ? si->thread : NULL);
if (si && si->thread) if (si && si->thread)
{ {