Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2002-12-11 07:00:04 +0300
committerChristopher Faylor <me@cgf.cx>2002-12-11 07:00:04 +0300
commit1d380f593ae54513419a7e7f31817fc23a5e69b9 (patch)
tree6997ee23c02f85f89c36ab4e7d971cd174c68869
parentea01c7f5d25779a88d6476da8b7f780379bc0c05 (diff)
* 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.
-rw-r--r--winsup/cygwin/ChangeLog32
-rw-r--r--winsup/cygwin/cygthread.cc66
-rw-r--r--winsup/cygwin/cygthread.h4
-rw-r--r--winsup/cygwin/exceptions.cc1
-rw-r--r--winsup/cygwin/fhandler.h3
-rw-r--r--winsup/cygwin/pipe.cc27
-rw-r--r--winsup/cygwin/select.cc46
7 files changed, 146 insertions, 33 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 51d79af9b..f3e21c767 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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.
diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc
index 27e7f9442..0c591d01f 100644
--- a/winsup/cygwin/cygthread.cc
+++ b/winsup/cygwin/cygthread.cc
@@ -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 (!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);
diff --git a/winsup/cygwin/cygthread.h b/winsup/cygwin/cygthread.h
index 774c656da..479a0682c 100644
--- a/winsup/cygwin/cygthread.h
+++ b/winsup/cygwin/cygthread.h
@@ -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 ()
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 380697eb0..bbd5518d0 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -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);
}
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 3dcc8b64d..56be17b59 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -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
diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc
index fe712e25e..49093728c 100644
--- a/winsup/cygwin/pipe.cc
+++ b/winsup/cygwin/pipe.cc
@@ -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 ()
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 369bea90f..d8d89999c 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -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)
{