* 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>
* net.cc (free_protoent_ptr): Add missing free() for base structure.
@ -6,16 +27,17 @@
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 ().
@ -23,7 +45,7 @@
(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.

View File

@ -9,14 +9,17 @@ details. */
#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;
@ -37,11 +40,12 @@ cygthread::stub (VOID *arg)
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)
{
@ -231,22 +235,72 @@ cygthread::exit_thread ()
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 (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);
free (this);

View File

@ -13,6 +13,7 @@ class cygthread
HANDLE h;
HANDLE ev;
HANDLE thread_sync;
void *stack_ptr;
const char *__name;
LPTHREAD_START_ROUTINE func;
VOID *arg;
@ -26,12 +27,13 @@ class cygthread
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 ()

View File

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

View File

@ -219,7 +219,7 @@ class fhandler_base
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); }
@ -473,6 +473,7 @@ class fhandler_pipe: public fhandler_base
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

View File

@ -22,6 +22,7 @@ details. */
#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";
@ -50,14 +51,36 @@ fhandler_pipe::set_close_on_exec (int 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
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 ()

View File

@ -431,7 +431,7 @@ peek_pipe (select_record *s, bool from_select)
{
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;
@ -521,7 +521,7 @@ struct pipeinf
static DWORD WINAPI
thread_pipe (void *arg)
{
pipeinf *pi = (pipeinf *)arg;
pipeinf *pi = (pipeinf *) arg;
BOOL gotone = FALSE;
for (;;)
@ -563,18 +563,18 @@ start_thread_pipe (select_record *me, select_stuff *stuff)
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;
@ -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 *
fhandler_pipe::select_read (select_record *s)
{
@ -631,7 +641,7 @@ static int
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;
@ -748,19 +758,19 @@ fhandler_console::select_except (select_record *s)
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
@ -846,7 +856,7 @@ peek_serial (select_record *s, bool)
{
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;
@ -944,7 +954,7 @@ err:
static DWORD WINAPI
thread_serial (void *arg)
{
serialinf *si = (serialinf *)arg;
serialinf *si = (serialinf *) arg;
BOOL gotone= FALSE;
for (;;)
@ -980,16 +990,16 @@ start_thread_serial (select_record *me, select_stuff *stuff)
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;
@ -1200,7 +1210,7 @@ static int start_thread_socket (select_record *, select_stuff *);
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);
@ -1243,7 +1253,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
{
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;
@ -1314,7 +1324,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
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;
@ -1327,7 +1337,7 @@ err:
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)
{