2000-02-18 03:38:33 +08:00
|
|
|
/* exceptions.cc
|
|
|
|
|
|
|
|
This file is part of Cygwin.
|
|
|
|
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
|
|
details. */
|
|
|
|
|
2009-01-03 13:12:22 +08:00
|
|
|
#define CYGTLS_HANDLE
|
2000-08-03 00:28:18 +08:00
|
|
|
#include "winsup.h"
|
2008-04-08 00:15:45 +08:00
|
|
|
#include "miscfuncs.h"
|
2000-08-22 13:10:20 +08:00
|
|
|
#include <imagehlp.h>
|
2001-11-15 11:25:52 +08:00
|
|
|
#include <stdlib.h>
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
#include <stdarg.h>
|
2005-12-28 04:07:59 +08:00
|
|
|
#include <syslog.h>
|
2008-04-03 23:28:03 +08:00
|
|
|
#include <wchar.h>
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2003-11-29 04:55:59 +08:00
|
|
|
#include "cygtls.h"
|
2012-07-22 06:58:20 +08:00
|
|
|
#include "pinfo.h"
|
2003-11-29 04:55:59 +08:00
|
|
|
#include "sigproc.h"
|
2000-09-08 00:23:51 +08:00
|
|
|
#include "shared_info.h"
|
2000-09-08 10:56:55 +08:00
|
|
|
#include "perprocess.h"
|
2005-10-04 01:23:54 +08:00
|
|
|
#include "path.h"
|
|
|
|
#include "fhandler.h"
|
|
|
|
#include "dtable.h"
|
|
|
|
#include "cygheap.h"
|
2006-05-22 12:50:54 +08:00
|
|
|
#include "child_info.h"
|
2008-02-28 23:50:51 +08:00
|
|
|
#include "ntdll.h"
|
2010-02-28 23:54:25 +08:00
|
|
|
#include "exception.h"
|
2019-01-22 22:23:05 +08:00
|
|
|
#include "posix_timer.h"
|
2020-08-20 22:35:43 +08:00
|
|
|
#include "gcc_seh.h"
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2022-05-17 20:12:32 +08:00
|
|
|
/* Define macros for CPU-agnostic register access. The _CX_foo
|
|
|
|
macros are for access into CONTEXT, the _MC_foo ones for access into
|
|
|
|
mcontext. The idea is to access the registers in terms of their job,
|
|
|
|
not in terms of their name on the given target. */
|
2013-04-23 17:44:36 +08:00
|
|
|
#ifdef __x86_64__
|
2022-05-17 20:12:32 +08:00
|
|
|
#define _CX_instPtr Rip
|
|
|
|
#define _CX_stackPtr Rsp
|
|
|
|
#define _CX_framePtr Rbp
|
|
|
|
/* For special register access inside mcontext. */
|
|
|
|
#define _MC_retReg rax
|
|
|
|
#define _MC_instPtr rip
|
|
|
|
#define _MC_stackPtr rsp
|
|
|
|
#define _MC_uclinkReg rbx /* MUST be callee-saved reg */
|
2013-04-23 17:44:36 +08:00
|
|
|
#else
|
2022-05-17 20:12:32 +08:00
|
|
|
#error unimplemented for this target
|
2013-04-23 17:44:36 +08:00
|
|
|
#endif
|
|
|
|
|
2011-07-07 00:33:30 +08:00
|
|
|
#define CALL_HANDLER_RETRY_OUTER 10
|
|
|
|
#define CALL_HANDLER_RETRY_INNER 10
|
2019-11-08 08:13:34 +08:00
|
|
|
#define DUMPSTACK_FRAME_LIMIT 32
|
2000-11-07 07:12:05 +08:00
|
|
|
|
2015-07-20 04:38:30 +08:00
|
|
|
PWCHAR debugger_command;
|
2024-01-12 04:00:14 +08:00
|
|
|
PWCHAR dumper_command;
|
2016-03-24 23:39:15 +08:00
|
|
|
extern uint8_t _sigbe;
|
|
|
|
extern uint8_t _sigdelayed_end;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2022-08-05 03:16:32 +08:00
|
|
|
static BOOL ctrl_c_handler (DWORD);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2013-04-23 17:44:36 +08:00
|
|
|
static const struct
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2013-01-21 12:34:52 +08:00
|
|
|
NTSTATUS code;
|
2000-02-18 03:38:33 +08:00
|
|
|
const char *name;
|
2001-10-13 09:35:15 +08:00
|
|
|
} status_info[] =
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
#define X(s) s, #s
|
|
|
|
{ X (STATUS_ABANDONED_WAIT_0) },
|
|
|
|
{ X (STATUS_ACCESS_VIOLATION) },
|
|
|
|
{ X (STATUS_ARRAY_BOUNDS_EXCEEDED) },
|
|
|
|
{ X (STATUS_BREAKPOINT) },
|
|
|
|
{ X (STATUS_CONTROL_C_EXIT) },
|
|
|
|
{ X (STATUS_DATATYPE_MISALIGNMENT) },
|
|
|
|
{ X (STATUS_FLOAT_DENORMAL_OPERAND) },
|
|
|
|
{ X (STATUS_FLOAT_DIVIDE_BY_ZERO) },
|
|
|
|
{ X (STATUS_FLOAT_INEXACT_RESULT) },
|
|
|
|
{ X (STATUS_FLOAT_INVALID_OPERATION) },
|
|
|
|
{ X (STATUS_FLOAT_OVERFLOW) },
|
|
|
|
{ X (STATUS_FLOAT_STACK_CHECK) },
|
|
|
|
{ X (STATUS_FLOAT_UNDERFLOW) },
|
|
|
|
{ X (STATUS_GUARD_PAGE_VIOLATION) },
|
|
|
|
{ X (STATUS_ILLEGAL_INSTRUCTION) },
|
|
|
|
{ X (STATUS_INTEGER_DIVIDE_BY_ZERO) },
|
|
|
|
{ X (STATUS_INTEGER_OVERFLOW) },
|
|
|
|
{ X (STATUS_INVALID_DISPOSITION) },
|
|
|
|
{ X (STATUS_IN_PAGE_ERROR) },
|
|
|
|
{ X (STATUS_NONCONTINUABLE_EXCEPTION) },
|
|
|
|
{ X (STATUS_NO_MEMORY) },
|
|
|
|
{ X (STATUS_PENDING) },
|
|
|
|
{ X (STATUS_PRIVILEGED_INSTRUCTION) },
|
|
|
|
{ X (STATUS_SINGLE_STEP) },
|
|
|
|
{ X (STATUS_STACK_OVERFLOW) },
|
|
|
|
{ X (STATUS_TIMEOUT) },
|
|
|
|
{ X (STATUS_USER_APC) },
|
|
|
|
{ X (STATUS_WAIT_0) },
|
|
|
|
{ 0, 0 }
|
|
|
|
#undef X
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Initialization code. */
|
|
|
|
|
|
|
|
void
|
2006-03-16 10:57:37 +08:00
|
|
|
init_console_handler (bool install_handler)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2005-06-30 10:52:14 +08:00
|
|
|
BOOL res;
|
2006-03-19 03:17:21 +08:00
|
|
|
|
2006-03-22 11:20:28 +08:00
|
|
|
SetConsoleCtrlHandler (ctrl_c_handler, FALSE);
|
2007-02-23 18:51:59 +08:00
|
|
|
SetConsoleCtrlHandler (NULL, FALSE);
|
2005-06-30 10:52:14 +08:00
|
|
|
if (install_handler)
|
|
|
|
res = SetConsoleCtrlHandler (ctrl_c_handler, TRUE);
|
|
|
|
else
|
2007-02-23 18:51:59 +08:00
|
|
|
res = SetConsoleCtrlHandler (NULL, TRUE);
|
2005-06-30 10:52:14 +08:00
|
|
|
if (!res)
|
2002-01-10 11:21:27 +08:00
|
|
|
system_printf ("SetConsoleCtrlHandler failed, %E");
|
2003-09-12 14:41:53 +08:00
|
|
|
}
|
2002-01-10 11:21:27 +08:00
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
extern "C" void
|
|
|
|
error_start_init (const char *buf)
|
|
|
|
{
|
|
|
|
if (!buf || !*buf)
|
2015-07-20 04:38:30 +08:00
|
|
|
return;
|
|
|
|
if (!debugger_command &&
|
|
|
|
!(debugger_command = (PWCHAR) malloc ((2 * NT_MAX_PATH + 20)
|
|
|
|
* sizeof (WCHAR))))
|
|
|
|
return;
|
|
|
|
|
|
|
|
PWCHAR cp = debugger_command
|
|
|
|
+ sys_mbstowcs (debugger_command, NT_MAX_PATH, buf) - 1;
|
|
|
|
cp = wcpcpy (cp, L" \"");
|
|
|
|
wcpcpy (cp, global_progname);
|
|
|
|
for (PWCHAR p = wcschr (cp, L'\\'); p; p = wcschr (p, L'\\'))
|
|
|
|
*p = L'/';
|
|
|
|
wcscat (cp, L"\"");
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2024-01-12 04:00:14 +08:00
|
|
|
extern "C" void
|
|
|
|
dumper_init (void)
|
|
|
|
{
|
|
|
|
WCHAR dll_dir[PATH_MAX];
|
|
|
|
if (!GetModuleFileNameW (cygwin_hmodule, dll_dir, PATH_MAX))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Strip off last path component ("\\cygwin1.dll") */
|
|
|
|
PWCHAR w = wcsrchr (dll_dir, L'\\');
|
|
|
|
if (!w)
|
|
|
|
return;
|
|
|
|
|
|
|
|
*w = L'\0';
|
|
|
|
|
|
|
|
/* Calculate the length of the command, allowing for an appended DWORD PID and
|
|
|
|
terminating null */
|
|
|
|
int cmd_len = 1 + wcslen(dll_dir) + 11 + 2 + 1 + wcslen(global_progname) + 1 + 10 + 1;
|
|
|
|
if (cmd_len > 32767)
|
|
|
|
{
|
|
|
|
/* If this comes to more than the 32,767 characters CreateProcess() can
|
|
|
|
accept, we can't work, so don't set dumper_command */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dumper_command = (PWCHAR) malloc(cmd_len * sizeof (WCHAR));
|
|
|
|
|
|
|
|
PWCHAR cp = dumper_command;
|
|
|
|
cp = wcpcpy (cp, L"\"");
|
|
|
|
cp = wcpcpy (cp, dll_dir);
|
|
|
|
cp = wcpcpy (cp, L"\\dumper.exe");
|
|
|
|
cp = wcpcpy (cp, L"\" ");
|
|
|
|
cp = wcpcpy (cp, L"\"");
|
|
|
|
cp = wcpcpy (cp, global_progname);
|
|
|
|
wcscat (cp, L"\"");
|
|
|
|
}
|
|
|
|
|
2014-01-09 00:51:20 +08:00
|
|
|
void
|
|
|
|
cygwin_exception::open_stackdumpfile ()
|
2001-04-30 11:09:19 +08:00
|
|
|
{
|
2010-08-18 22:22:07 +08:00
|
|
|
/* If we have no executable name, or if the CWD handle is NULL,
|
|
|
|
which means, the CWD is a virtual path, don't even try to open
|
|
|
|
a stackdump file. */
|
|
|
|
if (myself->progname[0] && cygheap->cwd.get_handle ())
|
2001-04-30 11:09:19 +08:00
|
|
|
{
|
2010-05-18 22:30:51 +08:00
|
|
|
const WCHAR *p;
|
2001-04-30 11:09:19 +08:00
|
|
|
/* write to progname.stackdump if possible */
|
2001-09-07 02:06:27 +08:00
|
|
|
if (!myself->progname[0])
|
2010-05-18 22:30:51 +08:00
|
|
|
p = L"unknown";
|
|
|
|
else if ((p = wcsrchr (myself->progname, L'\\')))
|
2001-04-30 11:09:19 +08:00
|
|
|
p++;
|
|
|
|
else
|
|
|
|
p = myself->progname;
|
2008-02-28 23:50:51 +08:00
|
|
|
|
2010-05-18 22:30:51 +08:00
|
|
|
WCHAR corefile[wcslen (p) + sizeof (".stackdump")];
|
2010-06-01 22:51:47 +08:00
|
|
|
wcpcpy (wcpcpy(corefile, p), L".stackdump");
|
2008-02-28 23:50:51 +08:00
|
|
|
UNICODE_STRING ucore;
|
|
|
|
OBJECT_ATTRIBUTES attr;
|
2008-02-29 01:09:34 +08:00
|
|
|
/* Create the UNICODE variation of <progname>.stackdump. */
|
2010-05-18 22:30:51 +08:00
|
|
|
RtlInitUnicodeString (&ucore, corefile);
|
2008-02-29 01:09:34 +08:00
|
|
|
/* Create an object attribute which refers to <progname>.stackdump
|
2008-07-17 04:20:45 +08:00
|
|
|
in Cygwin's cwd. Stick to caseinsensitivity. */
|
2008-02-28 23:50:51 +08:00
|
|
|
InitializeObjectAttributes (&attr, &ucore, OBJ_CASE_INSENSITIVE,
|
|
|
|
cygheap->cwd.get_handle (), NULL);
|
|
|
|
IO_STATUS_BLOCK io;
|
|
|
|
NTSTATUS status;
|
2008-02-29 01:09:34 +08:00
|
|
|
/* Try to open it to dump the stack in it. */
|
2008-02-28 23:50:51 +08:00
|
|
|
status = NtCreateFile (&h, GENERIC_WRITE | SYNCHRONIZE, &attr, &io,
|
2021-11-17 01:36:27 +08:00
|
|
|
NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
|
2008-02-28 23:50:51 +08:00
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT
|
2009-05-04 17:16:42 +08:00
|
|
|
| FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0);
|
2008-02-28 23:50:51 +08:00
|
|
|
if (NT_SUCCESS (status))
|
2001-04-30 11:09:19 +08:00
|
|
|
{
|
2004-11-26 12:15:10 +08:00
|
|
|
if (!myself->cygstarted)
|
2008-03-03 06:51:19 +08:00
|
|
|
system_printf ("Dumping stack trace to %S", &ucore);
|
2001-10-03 11:49:26 +08:00
|
|
|
else
|
2008-03-03 06:51:19 +08:00
|
|
|
debug_printf ("Dumping stack trace to %S", &ucore);
|
2001-04-30 11:09:19 +08:00
|
|
|
SetStdHandle (STD_ERROR_HANDLE, h);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
/* Utilities for dumping the stack, etc. */
|
|
|
|
|
2013-01-03 02:34:06 +08:00
|
|
|
void
|
|
|
|
cygwin_exception::dump_exception ()
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2000-08-03 03:26:01 +08:00
|
|
|
const char *exception_name = NULL;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2016-11-24 21:46:57 +08:00
|
|
|
for (int i = 0; status_info[i].name; i++)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2016-11-24 21:46:57 +08:00
|
|
|
if (status_info[i].code == (NTSTATUS) e->ExceptionCode)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2016-11-24 21:46:57 +08:00
|
|
|
exception_name = status_info[i].name;
|
|
|
|
break;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-23 17:44:36 +08:00
|
|
|
#ifdef __x86_64__
|
|
|
|
if (exception_name)
|
2022-10-28 22:24:00 +08:00
|
|
|
small_printf ("Exception: %s at rip=%012X\r\n", exception_name, ctx->Rip);
|
2013-04-23 17:44:36 +08:00
|
|
|
else
|
2022-10-28 22:24:00 +08:00
|
|
|
small_printf ("Signal %d at rip=%012X\r\n", e->ExceptionCode, ctx->Rip);
|
2015-06-19 22:12:10 +08:00
|
|
|
small_printf ("rax=%016X rbx=%016X rcx=%016X\r\n",
|
|
|
|
ctx->Rax, ctx->Rbx, ctx->Rcx);
|
|
|
|
small_printf ("rdx=%016X rsi=%016X rdi=%016X\r\n",
|
|
|
|
ctx->Rdx, ctx->Rsi, ctx->Rdi);
|
|
|
|
small_printf ("r8 =%016X r9 =%016X r10=%016X\r\n",
|
|
|
|
ctx->R8, ctx->R9, ctx->R10);
|
|
|
|
small_printf ("r11=%016X r12=%016X r13=%016X\r\n",
|
|
|
|
ctx->R11, ctx->R12, ctx->R13);
|
2013-04-23 17:44:36 +08:00
|
|
|
small_printf ("r14=%016X r15=%016X\r\n", ctx->R14, ctx->R15);
|
|
|
|
small_printf ("rbp=%016X rsp=%016X\r\n", ctx->Rbp, ctx->Rsp);
|
|
|
|
small_printf ("program=%W, pid %u, thread %s\r\n",
|
2018-01-24 16:34:23 +08:00
|
|
|
myself->progname, myself->pid, mythreadname ());
|
2000-02-18 03:38:33 +08:00
|
|
|
small_printf ("cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\r\n",
|
2015-06-19 22:12:10 +08:00
|
|
|
ctx->SegCs, ctx->SegDs, ctx->SegEs, ctx->SegFs,
|
|
|
|
ctx->SegGs, ctx->SegSs);
|
2022-05-17 20:12:32 +08:00
|
|
|
#else
|
|
|
|
#error unimplemented for this target
|
|
|
|
#endif
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* A class for manipulating the stack. */
|
|
|
|
class stack_info
|
|
|
|
{
|
2000-07-05 03:07:35 +08:00
|
|
|
int walk (); /* Uses the "old" method */
|
2000-07-04 04:14:06 +08:00
|
|
|
char *next_offset () {return *((char **) sf.AddrFrame.Offset);}
|
2001-05-05 10:44:36 +08:00
|
|
|
bool needargs;
|
2013-04-23 17:44:36 +08:00
|
|
|
PUINT_PTR dummy_frame;
|
|
|
|
CONTEXT c;
|
|
|
|
UNWIND_HISTORY_TABLE hist;
|
2015-06-19 21:58:23 +08:00
|
|
|
__tlsstack_t *sigstackptr;
|
2000-02-18 03:38:33 +08:00
|
|
|
public:
|
2001-05-05 10:44:36 +08:00
|
|
|
STACKFRAME sf; /* For storing the stack information */
|
2013-04-23 17:44:36 +08:00
|
|
|
void init (PUINT_PTR, bool, PCONTEXT); /* Called the first time that stack info is needed */
|
2000-03-10 05:04:05 +08:00
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
/* Postfix ++ iterates over the stack, returning zero when nothing is left. */
|
2003-02-04 11:01:17 +08:00
|
|
|
int operator ++(int) { return walk (); }
|
2000-02-18 03:38:33 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* The number of parameters used in STACKFRAME */
|
2000-07-05 03:07:35 +08:00
|
|
|
#define NPARAMS (sizeof (thestack.sf.Params) / sizeof (thestack.sf.Params[0]))
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
/* This is the main stack frame info for this process. */
|
2000-03-10 05:04:05 +08:00
|
|
|
static NO_COPY stack_info thestack;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
/* Initialize everything needed to start iterating. */
|
|
|
|
void
|
2013-04-23 17:44:36 +08:00
|
|
|
stack_info::init (PUINT_PTR framep, bool wantargs, PCONTEXT ctx)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2013-04-23 17:44:36 +08:00
|
|
|
memset (&hist, 0, sizeof hist);
|
|
|
|
if (ctx)
|
|
|
|
memcpy (&c, ctx, sizeof c);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memset (&c, 0, sizeof c);
|
|
|
|
c.ContextFlags = CONTEXT_ALL;
|
|
|
|
}
|
2015-03-10 05:55:29 +08:00
|
|
|
sigstackptr = _my_tls.stackptr;
|
2000-07-05 03:07:35 +08:00
|
|
|
memset (&sf, 0, sizeof (sf));
|
2013-04-23 17:44:36 +08:00
|
|
|
if (ctx)
|
|
|
|
sf.AddrFrame.Offset = (UINT_PTR) framep;
|
2001-05-05 10:44:36 +08:00
|
|
|
else
|
|
|
|
{
|
2013-04-23 17:44:36 +08:00
|
|
|
dummy_frame = framep;
|
|
|
|
sf.AddrFrame.Offset = (UINT_PTR) &dummy_frame;
|
2001-05-05 10:44:36 +08:00
|
|
|
}
|
2013-04-23 17:44:36 +08:00
|
|
|
if (framep)
|
|
|
|
sf.AddrReturn.Offset = framep[1];
|
2000-02-18 03:38:33 +08:00
|
|
|
sf.AddrFrame.Mode = AddrModeFlat;
|
2001-05-05 10:44:36 +08:00
|
|
|
needargs = wantargs;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2008-08-02 03:12:49 +08:00
|
|
|
extern "C" void _cygwin_exit_return ();
|
|
|
|
|
2015-07-17 22:29:41 +08:00
|
|
|
static inline void
|
|
|
|
__unwind_single_frame (PCONTEXT ctx)
|
|
|
|
{
|
2013-04-23 17:44:36 +08:00
|
|
|
PRUNTIME_FUNCTION f;
|
|
|
|
ULONG64 imagebase;
|
2017-10-09 23:37:40 +08:00
|
|
|
UNWIND_HISTORY_TABLE hist = {0};
|
2013-04-23 17:44:36 +08:00
|
|
|
DWORD64 establisher;
|
|
|
|
PVOID hdl;
|
|
|
|
|
2022-05-17 20:12:32 +08:00
|
|
|
f = RtlLookupFunctionEntry (ctx->_CX_instPtr, &imagebase, &hist);
|
2015-07-17 22:29:41 +08:00
|
|
|
if (f)
|
2022-05-17 20:12:32 +08:00
|
|
|
RtlVirtualUnwind (0, imagebase, ctx->_CX_instPtr, f, ctx, &hdl,
|
|
|
|
&establisher, NULL);
|
2015-07-17 22:29:41 +08:00
|
|
|
else
|
|
|
|
{
|
2022-05-17 20:12:32 +08:00
|
|
|
ctx->_CX_instPtr = *(ULONG_PTR *) ctx->_CX_stackPtr;
|
|
|
|
ctx->_CX_stackPtr += 8;
|
2015-07-17 22:29:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Walk the stack.
|
|
|
|
|
|
|
|
On 32 bit we're doing this by looking at successive stored 'ebp' frames.
|
|
|
|
This is not foolproof. */
|
|
|
|
int
|
|
|
|
stack_info::walk ()
|
|
|
|
{
|
2022-05-17 20:12:32 +08:00
|
|
|
if (!c._CX_instPtr)
|
2013-04-23 17:44:36 +08:00
|
|
|
return 0;
|
|
|
|
|
2022-05-17 20:12:32 +08:00
|
|
|
sf.AddrPC.Offset = c._CX_instPtr;
|
|
|
|
sf.AddrStack.Offset = c._CX_stackPtr;
|
|
|
|
sf.AddrFrame.Offset = c._CX_framePtr;
|
2013-04-23 17:44:36 +08:00
|
|
|
|
2022-05-17 20:12:32 +08:00
|
|
|
if ((c._CX_instPtr >= (DWORD64)&_sigbe)
|
|
|
|
&& (c._CX_instPtr < (DWORD64)&_sigdelayed_end))
|
2015-03-10 05:55:29 +08:00
|
|
|
{
|
|
|
|
/* _sigbe and sigdelayed don't have SEH unwinding data, so virtually
|
|
|
|
unwind the tls sigstack */
|
2022-05-17 20:12:32 +08:00
|
|
|
c._CX_instPtr = sigstackptr[-1];
|
2015-03-10 05:55:29 +08:00
|
|
|
sigstackptr--;
|
|
|
|
return 1;
|
|
|
|
}
|
2015-07-17 22:29:41 +08:00
|
|
|
__unwind_single_frame (&c);
|
2022-05-17 20:12:32 +08:00
|
|
|
if (needargs && c._CX_instPtr)
|
2013-04-23 17:44:36 +08:00
|
|
|
{
|
2022-05-17 20:12:32 +08:00
|
|
|
PULONG_PTR p = (PULONG_PTR) c._CX_stackPtr;
|
2013-04-23 17:44:36 +08:00
|
|
|
for (unsigned i = 0; i < NPARAMS; ++i)
|
|
|
|
sf.Params[i] = p[i + 1];
|
|
|
|
}
|
|
|
|
return 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
Cygwin: Add addresses as module offsets in .stackdump file
This adds an additional column to the stack trace in a .stackdump file,
which gives the stack frame return address as a module name+offset. This
makes it a possible to convert the address to a function name without
having to guess what module the address belongs to.
> Stack trace:
> Frame Function Args
> 0007FFFFCC30 0001004010E9 (000180048055, 000180046FA0, 000000000002, 00018031E160) segv-test.exe+0x10E9
> 0007FFFFCD30 0001800480C1 (000000000000, 000000000000, 000000000000, 000000000000) cygwin1.dll+0x80C1
> 0007FFFFFFF0 000180045C86 (000000000000, 000000000000, 000000000000, 000000000000) cygwin1.dll+0x5C86
> 0007FFFFFFF0 000180045D34 (000000000000, 000000000000, 000000000000, 000000000000) cygwin1.dll+0x5D34
> End of stack trace
Loosely based on this patch [1] by Brian Dessent.
[1] https://cygwin.com/pipermail/cygwin-patches/2008q1/006306.html
2022-10-28 19:26:56 +08:00
|
|
|
/*
|
|
|
|
Walk the list of modules in the current process to find the one containing
|
|
|
|
'func_va'.
|
|
|
|
|
|
|
|
This implementation requires no allocation of memory and minimal system
|
|
|
|
calls, so it should be safe in the context of an exception handler.
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
prettyprint_va (PVOID func_va)
|
|
|
|
{
|
|
|
|
static char buf[256];
|
|
|
|
buf[0] = '\0';
|
|
|
|
|
|
|
|
PLIST_ENTRY head = &NtCurrentTeb()->Peb->Ldr->InMemoryOrderModuleList;
|
|
|
|
for (PLIST_ENTRY x = head->Flink; x != head; x = x->Flink)
|
|
|
|
{
|
|
|
|
PLDR_DATA_TABLE_ENTRY mod = CONTAINING_RECORD (x, LDR_DATA_TABLE_ENTRY,
|
|
|
|
InMemoryOrderLinks);
|
2022-11-01 22:01:08 +08:00
|
|
|
if ((func_va < mod->DllBase) ||
|
|
|
|
(func_va > (PVOID)((DWORD_PTR)mod->DllBase + mod->SizeOfImage)))
|
Cygwin: Add addresses as module offsets in .stackdump file
This adds an additional column to the stack trace in a .stackdump file,
which gives the stack frame return address as a module name+offset. This
makes it a possible to convert the address to a function name without
having to guess what module the address belongs to.
> Stack trace:
> Frame Function Args
> 0007FFFFCC30 0001004010E9 (000180048055, 000180046FA0, 000000000002, 00018031E160) segv-test.exe+0x10E9
> 0007FFFFCD30 0001800480C1 (000000000000, 000000000000, 000000000000, 000000000000) cygwin1.dll+0x80C1
> 0007FFFFFFF0 000180045C86 (000000000000, 000000000000, 000000000000, 000000000000) cygwin1.dll+0x5C86
> 0007FFFFFFF0 000180045D34 (000000000000, 000000000000, 000000000000, 000000000000) cygwin1.dll+0x5D34
> End of stack trace
Loosely based on this patch [1] by Brian Dessent.
[1] https://cygwin.com/pipermail/cygwin-patches/2008q1/006306.html
2022-10-28 19:26:56 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
__small_sprintf (buf, "%S+0x%x", &mod->BaseDllName,
|
|
|
|
(DWORD_PTR)func_va - (DWORD_PTR)mod->DllBase);
|
2022-11-01 22:01:08 +08:00
|
|
|
break;
|
Cygwin: Add addresses as module offsets in .stackdump file
This adds an additional column to the stack trace in a .stackdump file,
which gives the stack frame return address as a module name+offset. This
makes it a possible to convert the address to a function name without
having to guess what module the address belongs to.
> Stack trace:
> Frame Function Args
> 0007FFFFCC30 0001004010E9 (000180048055, 000180046FA0, 000000000002, 00018031E160) segv-test.exe+0x10E9
> 0007FFFFCD30 0001800480C1 (000000000000, 000000000000, 000000000000, 000000000000) cygwin1.dll+0x80C1
> 0007FFFFFFF0 000180045C86 (000000000000, 000000000000, 000000000000, 000000000000) cygwin1.dll+0x5C86
> 0007FFFFFFF0 000180045D34 (000000000000, 000000000000, 000000000000, 000000000000) cygwin1.dll+0x5D34
> End of stack trace
Loosely based on this patch [1] by Brian Dessent.
[1] https://cygwin.com/pipermail/cygwin-patches/2008q1/006306.html
2022-10-28 19:26:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2011-11-27 03:14:22 +08:00
|
|
|
void
|
2013-01-03 02:34:06 +08:00
|
|
|
cygwin_exception::dumpstack ()
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2006-02-20 10:04:31 +08:00
|
|
|
static bool already_dumped;
|
2001-04-30 11:09:19 +08:00
|
|
|
|
2014-08-22 17:21:33 +08:00
|
|
|
__try
|
|
|
|
{
|
|
|
|
if (already_dumped || cygheap->rlim_core == 0Ul)
|
|
|
|
return;
|
|
|
|
already_dumped = true;
|
|
|
|
open_stackdumpfile ();
|
2012-02-13 06:43:33 +08:00
|
|
|
|
2014-08-22 17:21:33 +08:00
|
|
|
if (e)
|
|
|
|
dump_exception ();
|
2006-02-20 10:04:31 +08:00
|
|
|
|
2014-08-22 17:21:33 +08:00
|
|
|
int i;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2014-08-22 17:21:33 +08:00
|
|
|
thestack.init (framep, 1, ctx); /* Initialize from the input CONTEXT */
|
2022-10-28 20:43:54 +08:00
|
|
|
small_printf ("Stack trace:\r\nFrame Function Args\r\n");
|
2019-11-08 08:13:34 +08:00
|
|
|
for (i = 0; i < DUMPSTACK_FRAME_LIMIT && thestack++; i++)
|
2014-08-22 17:21:33 +08:00
|
|
|
{
|
2022-10-28 22:24:00 +08:00
|
|
|
small_printf ("%012X %012X", thestack.sf.AddrFrame.Offset,
|
2014-08-22 17:21:33 +08:00
|
|
|
thestack.sf.AddrPC.Offset);
|
|
|
|
for (unsigned j = 0; j < NPARAMS; j++)
|
2022-10-28 22:24:00 +08:00
|
|
|
small_printf ("%s%012X", j == 0 ? " (" : ", ",
|
2014-08-22 17:21:33 +08:00
|
|
|
thestack.sf.Params[j]);
|
Cygwin: Add addresses as module offsets in .stackdump file
This adds an additional column to the stack trace in a .stackdump file,
which gives the stack frame return address as a module name+offset. This
makes it a possible to convert the address to a function name without
having to guess what module the address belongs to.
> Stack trace:
> Frame Function Args
> 0007FFFFCC30 0001004010E9 (000180048055, 000180046FA0, 000000000002, 00018031E160) segv-test.exe+0x10E9
> 0007FFFFCD30 0001800480C1 (000000000000, 000000000000, 000000000000, 000000000000) cygwin1.dll+0x80C1
> 0007FFFFFFF0 000180045C86 (000000000000, 000000000000, 000000000000, 000000000000) cygwin1.dll+0x5C86
> 0007FFFFFFF0 000180045D34 (000000000000, 000000000000, 000000000000, 000000000000) cygwin1.dll+0x5D34
> End of stack trace
Loosely based on this patch [1] by Brian Dessent.
[1] https://cygwin.com/pipermail/cygwin-patches/2008q1/006306.html
2022-10-28 19:26:56 +08:00
|
|
|
small_printf (") %s\r\n", prettyprint_va((PVOID)thestack.sf.AddrPC.Offset));
|
2014-08-22 17:21:33 +08:00
|
|
|
}
|
2022-10-28 20:43:54 +08:00
|
|
|
small_printf ("End of stack trace%s\r\n",
|
2019-11-08 08:13:34 +08:00
|
|
|
i == DUMPSTACK_FRAME_LIMIT ?
|
2022-10-28 20:43:54 +08:00
|
|
|
" (more stack frames may be present)" : "");
|
2022-10-28 20:35:13 +08:00
|
|
|
|
|
|
|
small_printf ("Loaded modules:\r\n");
|
|
|
|
PLIST_ENTRY head = &NtCurrentTeb()->Peb->Ldr->InMemoryOrderModuleList;
|
|
|
|
for (PLIST_ENTRY x = head->Flink; x != head; x = x->Flink)
|
|
|
|
{
|
|
|
|
PLDR_DATA_TABLE_ENTRY mod = CONTAINING_RECORD (x, LDR_DATA_TABLE_ENTRY,
|
|
|
|
InMemoryOrderLinks);
|
|
|
|
small_printf ("%012X %S\r\n", mod->DllBase, &mod->BaseDllName);
|
|
|
|
}
|
|
|
|
|
2014-08-22 17:21:33 +08:00
|
|
|
if (h)
|
|
|
|
NtClose (h);
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
2014-08-22 17:21:33 +08:00
|
|
|
__except (NO_ERROR) {}
|
|
|
|
__endtry
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2007-07-29 13:22:05 +08:00
|
|
|
bool
|
|
|
|
_cygtls::inside_kernel (CONTEXT *cx)
|
2005-12-28 04:07:59 +08:00
|
|
|
{
|
|
|
|
int res;
|
|
|
|
MEMORY_BASIC_INFORMATION m;
|
2006-02-24 03:21:21 +08:00
|
|
|
|
2007-07-29 13:22:05 +08:00
|
|
|
if (!isinitialized ())
|
2006-02-24 03:21:21 +08:00
|
|
|
return true;
|
2005-12-28 04:07:59 +08:00
|
|
|
|
|
|
|
memset (&m, 0, sizeof m);
|
2022-05-17 20:12:32 +08:00
|
|
|
if (!VirtualQuery ((LPCVOID) cx->_CX_instPtr, &m, sizeof m))
|
|
|
|
sigproc_printf ("couldn't get memory info, pc %p, %E", cx->_CX_instPtr);
|
2005-12-28 04:07:59 +08:00
|
|
|
|
2008-04-03 23:28:03 +08:00
|
|
|
size_t size = (windows_system_directory_length + 6) * sizeof (WCHAR);
|
|
|
|
PWCHAR checkdir = (PWCHAR) alloca (size);
|
|
|
|
memset (checkdir, 0, size);
|
2005-12-28 04:07:59 +08:00
|
|
|
|
|
|
|
# define h ((HMODULE) m.AllocationBase)
|
2011-12-14 04:06:31 +08:00
|
|
|
if (!h || m.State != MEM_COMMIT) /* Be defensive */
|
2005-12-28 04:07:59 +08:00
|
|
|
res = true;
|
2013-12-10 04:32:24 +08:00
|
|
|
else if (h == hntdll)
|
|
|
|
res = true; /* Calling GetModuleFilename on ntdll.dll
|
|
|
|
can hang */
|
2006-02-24 03:21:21 +08:00
|
|
|
else if (h == user_data->hmodule)
|
|
|
|
res = false;
|
2015-06-19 22:12:10 +08:00
|
|
|
else if (!GetModuleFileNameW (h, checkdir,
|
|
|
|
windows_system_directory_length + 6))
|
2006-02-24 03:21:21 +08:00
|
|
|
res = false;
|
2005-12-28 04:07:59 +08:00
|
|
|
else
|
2008-04-03 23:28:03 +08:00
|
|
|
{
|
|
|
|
/* Skip potential long path prefix. */
|
|
|
|
if (!wcsncmp (checkdir, L"\\\\?\\", 4))
|
|
|
|
checkdir += 4;
|
2011-12-14 04:06:31 +08:00
|
|
|
res = wcsncasecmp (windows_system_directory, checkdir,
|
|
|
|
windows_system_directory_length) == 0;
|
2008-04-03 23:28:03 +08:00
|
|
|
}
|
2022-05-17 20:12:32 +08:00
|
|
|
sigproc_printf ("pc %p, h %p, inside_kernel %d", cx->_CX_instPtr, h, res);
|
2005-12-28 04:07:59 +08:00
|
|
|
# undef h
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
/* Temporary (?) function for external callers to get a stack dump */
|
|
|
|
extern "C" void
|
2000-07-05 03:07:35 +08:00
|
|
|
cygwin_stackdump ()
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
CONTEXT c;
|
|
|
|
c.ContextFlags = CONTEXT_FULL;
|
2013-04-23 17:44:36 +08:00
|
|
|
RtlCaptureContext (&c);
|
2022-05-17 20:12:32 +08:00
|
|
|
cygwin_exception exc ((PUINT_PTR) c._CX_framePtr, &c);
|
2013-01-03 02:34:06 +08:00
|
|
|
exc.dumpstack ();
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2024-01-12 04:00:14 +08:00
|
|
|
static
|
|
|
|
int exec_prepared_command (PWCHAR command)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2024-01-12 04:00:14 +08:00
|
|
|
if (!command)
|
2000-02-18 03:38:33 +08:00
|
|
|
return 0;
|
2024-01-12 04:00:14 +08:00
|
|
|
debug_printf ("executing prepared command '%W'", command);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2024-01-12 04:00:14 +08:00
|
|
|
PWCHAR dbg_end = wcschr (command, L'\0');
|
2015-07-20 04:38:30 +08:00
|
|
|
__small_swprintf (dbg_end, L" %u", GetCurrentProcessId ());
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2003-02-07 23:00:57 +08:00
|
|
|
LONG prio = GetThreadPriority (GetCurrentThread ());
|
|
|
|
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
|
2000-02-23 12:07:13 +08:00
|
|
|
PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2015-06-19 22:12:10 +08:00
|
|
|
STARTUPINFOW si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
NULL, NULL, NULL, NULL};
|
2000-02-18 03:38:33 +08:00
|
|
|
si.lpReserved = NULL;
|
|
|
|
si.lpDesktop = NULL;
|
|
|
|
si.dwFlags = 0;
|
|
|
|
si.cb = sizeof (si);
|
|
|
|
|
|
|
|
/* FIXME: need to know handles of all running threads to
|
|
|
|
suspend_all_threads_except (current_thread_id);
|
|
|
|
*/
|
|
|
|
|
2010-10-24 23:26:05 +08:00
|
|
|
/* If the tty mutex is owned, we will fail to start any cygwin app
|
|
|
|
until the trapped app exits. However, this will only release any
|
|
|
|
the mutex if it is owned by this thread so that may be problematic. */
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2006-06-04 04:32:07 +08:00
|
|
|
lock_ttys::release ();
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2000-07-05 03:07:35 +08:00
|
|
|
/* prevent recursive exception handling */
|
2008-04-03 23:28:03 +08:00
|
|
|
PWCHAR rawenv = GetEnvironmentStringsW () ;
|
|
|
|
for (PWCHAR p = rawenv; *p != L'\0'; p = wcschr (p, L'\0') + 1)
|
2000-07-05 03:07:35 +08:00
|
|
|
{
|
2008-04-03 23:28:03 +08:00
|
|
|
if (wcsncmp (p, L"CYGWIN=", wcslen (L"CYGWIN=")) == 0)
|
2000-07-05 03:07:35 +08:00
|
|
|
{
|
2008-04-03 23:28:03 +08:00
|
|
|
PWCHAR q = wcsstr (p, L"error_start") ;
|
2000-07-05 03:07:35 +08:00
|
|
|
/* replace 'error_start=...' with '_rror_start=...' */
|
2003-12-27 08:25:02 +08:00
|
|
|
if (q)
|
|
|
|
{
|
2008-04-03 23:28:03 +08:00
|
|
|
*q = L'_' ;
|
|
|
|
SetEnvironmentVariableW (L"CYGWIN", p + wcslen (L"CYGWIN=")) ;
|
2003-12-27 08:25:02 +08:00
|
|
|
}
|
2014-06-23 21:23:14 +08:00
|
|
|
break;
|
2000-07-05 03:07:35 +08:00
|
|
|
}
|
|
|
|
}
|
2014-06-23 21:23:14 +08:00
|
|
|
FreeEnvironmentStringsW (rawenv);
|
2000-07-05 03:07:35 +08:00
|
|
|
|
2024-01-12 04:00:14 +08:00
|
|
|
console_printf ("*** starting '%W' for pid %u, tid %u\r\n",
|
|
|
|
command,
|
2004-03-15 23:50:20 +08:00
|
|
|
cygwin_pid (GetCurrentProcessId ()), GetCurrentThreadId ());
|
2002-07-15 11:48:52 +08:00
|
|
|
BOOL dbg;
|
2007-12-12 20:12:24 +08:00
|
|
|
dbg = CreateProcessW (NULL,
|
2024-01-12 04:00:14 +08:00
|
|
|
command,
|
2007-12-12 20:12:24 +08:00
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
FALSE,
|
|
|
|
CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&si,
|
|
|
|
&pi);
|
2001-04-30 11:09:19 +08:00
|
|
|
|
2020-08-27 23:12:47 +08:00
|
|
|
/* We want to stop here and wait until the error_start process attaches. But
|
|
|
|
we can't wait here for the error_start process to exit, as if it's a
|
|
|
|
debugger, it might want to continue this thread. So we busy wait until a
|
|
|
|
debugger attaches, which stops this process, after which it can decide if
|
2024-01-12 04:00:14 +08:00
|
|
|
we continue or not.
|
|
|
|
|
|
|
|
Note that this is still racy: if the error_start process does it's work too
|
|
|
|
fast, we don't notice that it attached and get stuck here.
|
|
|
|
*/
|
2020-08-27 23:12:47 +08:00
|
|
|
|
2015-07-20 04:38:30 +08:00
|
|
|
*dbg_end = L'\0';
|
2001-11-24 11:11:39 +08:00
|
|
|
if (!dbg)
|
2024-01-12 04:00:14 +08:00
|
|
|
system_printf ("Failed to start, %E");
|
2001-11-24 11:11:39 +08:00
|
|
|
else
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2003-02-14 10:52:29 +08:00
|
|
|
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
|
2002-05-27 10:25:28 +08:00
|
|
|
while (!being_debugged ())
|
2013-06-09 00:54:41 +08:00
|
|
|
Sleep (1);
|
2004-01-27 02:52:02 +08:00
|
|
|
Sleep (2000);
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2024-01-12 04:00:14 +08:00
|
|
|
console_printf ("*** continuing pid %u\r\n",
|
|
|
|
cygwin_pid (GetCurrentProcessId ()));
|
2004-02-09 03:59:27 +08:00
|
|
|
|
2003-11-29 04:55:59 +08:00
|
|
|
SetThreadPriority (GetCurrentThread (), prio);
|
2004-02-09 03:59:27 +08:00
|
|
|
return dbg;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2024-01-12 04:00:14 +08:00
|
|
|
extern "C" int
|
|
|
|
try_to_debug ()
|
|
|
|
{
|
|
|
|
/* If already being debugged, break into the debugger (Note that this function
|
|
|
|
can be called from places other than an exception) */
|
|
|
|
if (being_debugged ())
|
|
|
|
{
|
|
|
|
extern void break_here ();
|
|
|
|
break_here ();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Otherwise, invoke the JIT debugger, if set */
|
|
|
|
return exec_prepared_command (debugger_command);
|
|
|
|
}
|
|
|
|
|
2014-08-22 17:21:33 +08:00
|
|
|
/* myfault exception handler. */
|
|
|
|
EXCEPTION_DISPOSITION
|
|
|
|
exception::myfault (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
|
|
|
|
PDISPATCHER_CONTEXT dispatch)
|
2014-03-20 00:08:21 +08:00
|
|
|
{
|
2014-08-22 17:21:33 +08:00
|
|
|
PSCOPE_TABLE table = (PSCOPE_TABLE) dispatch->HandlerData;
|
|
|
|
RtlUnwindEx (frame,
|
|
|
|
(char *) dispatch->ImageBase + table->ScopeRecord[0].JumpTarget,
|
|
|
|
e, 0, in, dispatch->HistoryTable);
|
|
|
|
/* NOTREACHED, make gcc happy. */
|
|
|
|
return ExceptionContinueSearch;
|
2014-03-20 00:08:21 +08:00
|
|
|
}
|
2015-07-08 02:45:06 +08:00
|
|
|
|
|
|
|
/* If another exception occurs while running a signal handler on an alternate
|
|
|
|
signal stack, the normal SEH handlers are skipped, because the OS exception
|
|
|
|
handling considers the current (alternate) stack "broken". However, it
|
|
|
|
still calls vectored exception handlers.
|
|
|
|
|
|
|
|
TODO: What we do here is to handle only __try/__except blocks in Cygwin.
|
|
|
|
"Normal" exceptions will simply exit the process. Still, better
|
|
|
|
than nothing... */
|
2022-08-05 03:16:32 +08:00
|
|
|
LONG
|
2015-07-08 02:45:06 +08:00
|
|
|
myfault_altstack_handler (EXCEPTION_POINTERS *exc)
|
|
|
|
{
|
|
|
|
_cygtls& me = _my_tls;
|
|
|
|
|
|
|
|
if (me.andreas)
|
|
|
|
{
|
|
|
|
CONTEXT *c = exc->ContextRecord;
|
|
|
|
|
|
|
|
/* Unwind the stack manually and call RtlRestoreContext. This
|
|
|
|
is necessary because RtlUnwindEx checks the stack for validity,
|
|
|
|
which, as outlined above, fails for the alternate stack. */
|
2022-05-17 20:12:32 +08:00
|
|
|
while (c->_CX_stackPtr < me.andreas->frame)
|
2015-07-17 22:29:41 +08:00
|
|
|
__unwind_single_frame (c);
|
2022-05-17 20:12:32 +08:00
|
|
|
c->_CX_instPtr = me.andreas->ret;
|
2015-07-08 02:45:06 +08:00
|
|
|
RtlRestoreContext (c, NULL);
|
|
|
|
}
|
|
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
|
|
}
|
|
|
|
|
2014-03-29 06:31:53 +08:00
|
|
|
/* Main exception handler. */
|
2014-08-22 17:21:33 +08:00
|
|
|
EXCEPTION_DISPOSITION
|
|
|
|
exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
|
|
|
|
PDISPATCHER_CONTEXT dispatch)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2016-02-13 01:17:35 +08:00
|
|
|
static int NO_COPY debugging = 0;
|
2005-07-03 10:40:30 +08:00
|
|
|
_cygtls& me = _my_tls;
|
2001-04-30 11:09:19 +08:00
|
|
|
|
2001-05-24 13:20:17 +08:00
|
|
|
if (debugging && ++debugging < 500000)
|
2001-05-05 13:07:20 +08:00
|
|
|
{
|
2009-12-21 17:38:25 +08:00
|
|
|
SetThreadPriority (hMainThread, THREAD_PRIORITY_NORMAL);
|
2014-03-29 06:31:53 +08:00
|
|
|
return ExceptionContinueExecution;
|
2001-05-05 13:07:20 +08:00
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2013-05-01 07:47:01 +08:00
|
|
|
/* If we're exiting, tell Windows to keep looking for an
|
|
|
|
exception handler. */
|
2012-12-29 02:06:17 +08:00
|
|
|
if (exit_state || e->ExceptionFlags)
|
2014-03-29 06:31:53 +08:00
|
|
|
return ExceptionContinueSearch;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2013-01-03 02:34:06 +08:00
|
|
|
siginfo_t si = {};
|
2005-09-26 22:51:48 +08:00
|
|
|
si.si_code = SI_KERNEL;
|
2000-02-18 03:38:33 +08:00
|
|
|
/* Coerce win32 value to posix value. */
|
2005-12-03 12:23:35 +08:00
|
|
|
switch (e->ExceptionCode)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
case STATUS_FLOAT_DIVIDE_BY_ZERO:
|
2018-06-26 16:09:29 +08:00
|
|
|
si.si_signo = SIGFPE;
|
|
|
|
si.si_code = FPE_FLTDIV;
|
|
|
|
break;
|
|
|
|
case STATUS_FLOAT_DENORMAL_OPERAND:
|
2000-02-18 03:38:33 +08:00
|
|
|
case STATUS_FLOAT_INVALID_OPERATION:
|
2018-06-26 16:09:29 +08:00
|
|
|
si.si_signo = SIGFPE;
|
|
|
|
si.si_code = FPE_FLTINV;
|
|
|
|
break;
|
2000-02-18 03:38:33 +08:00
|
|
|
case STATUS_FLOAT_STACK_CHECK:
|
2004-01-19 13:46:54 +08:00
|
|
|
si.si_signo = SIGFPE;
|
2005-09-26 21:23:47 +08:00
|
|
|
si.si_code = FPE_FLTSUB;
|
2004-01-19 13:46:54 +08:00
|
|
|
break;
|
|
|
|
case STATUS_FLOAT_INEXACT_RESULT:
|
|
|
|
si.si_signo = SIGFPE;
|
2005-09-26 21:23:47 +08:00
|
|
|
si.si_code = FPE_FLTRES;
|
2004-01-19 13:46:54 +08:00
|
|
|
break;
|
|
|
|
case STATUS_FLOAT_OVERFLOW:
|
|
|
|
si.si_signo = SIGFPE;
|
2005-09-26 21:23:47 +08:00
|
|
|
si.si_code = FPE_FLTOVF;
|
2004-01-19 13:46:54 +08:00
|
|
|
break;
|
2000-02-18 03:38:33 +08:00
|
|
|
case STATUS_FLOAT_UNDERFLOW:
|
2004-01-19 13:46:54 +08:00
|
|
|
si.si_signo = SIGFPE;
|
2005-09-26 21:23:47 +08:00
|
|
|
si.si_code = FPE_FLTUND;
|
2004-01-19 13:46:54 +08:00
|
|
|
break;
|
2000-02-18 03:38:33 +08:00
|
|
|
case STATUS_INTEGER_DIVIDE_BY_ZERO:
|
2004-01-19 13:46:54 +08:00
|
|
|
si.si_signo = SIGFPE;
|
2005-09-26 21:23:47 +08:00
|
|
|
si.si_code = FPE_INTDIV;
|
2004-01-19 13:46:54 +08:00
|
|
|
break;
|
2000-02-18 03:38:33 +08:00
|
|
|
case STATUS_INTEGER_OVERFLOW:
|
2004-01-19 13:46:54 +08:00
|
|
|
si.si_signo = SIGFPE;
|
2005-09-26 21:23:47 +08:00
|
|
|
si.si_code = FPE_INTOVF;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATUS_ILLEGAL_INSTRUCTION:
|
2004-01-19 13:46:54 +08:00
|
|
|
si.si_signo = SIGILL;
|
2005-09-26 21:23:47 +08:00
|
|
|
si.si_code = ILL_ILLOPC;
|
2004-01-19 13:46:54 +08:00
|
|
|
break;
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
case STATUS_PRIVILEGED_INSTRUCTION:
|
2004-01-19 13:46:54 +08:00
|
|
|
si.si_signo = SIGILL;
|
2005-09-26 21:23:47 +08:00
|
|
|
si.si_code = ILL_PRVOPC;
|
2004-01-19 13:46:54 +08:00
|
|
|
break;
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
case STATUS_NONCONTINUABLE_EXCEPTION:
|
2004-01-19 13:46:54 +08:00
|
|
|
si.si_signo = SIGILL;
|
2005-09-26 21:23:47 +08:00
|
|
|
si.si_code = ILL_ILLADR;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATUS_TIMEOUT:
|
2004-01-19 13:46:54 +08:00
|
|
|
si.si_signo = SIGALRM;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
|
2005-12-02 04:52:00 +08:00
|
|
|
case STATUS_GUARD_PAGE_VIOLATION:
|
|
|
|
si.si_signo = SIGBUS;
|
|
|
|
si.si_code = BUS_OBJERR;
|
|
|
|
break;
|
|
|
|
|
2005-12-28 04:07:59 +08:00
|
|
|
case STATUS_DATATYPE_MISALIGNMENT:
|
|
|
|
si.si_signo = SIGBUS;
|
|
|
|
si.si_code = BUS_ADRALN;
|
|
|
|
break;
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
case STATUS_ACCESS_VIOLATION:
|
2006-07-25 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/version.h: Bump DLL version to 1.7.0.
2006-07-25 Corinna Vinschen <corinna@vinschen.de>
* select.h: Remove.
* fhandler_socket.cc: Don't include select.h.
* select.cc: Ditto.
2006-07-25 Corinna Vinschen <corinna@vinschen.de>
* cygtls.h: Drop socket related includes.
(struct _local_storage): Remove exitsock and exitsock_sin. Add
select_sockevt.
* cygtls.cc: Accomodate above change throughout.
* fhandler.h (class fhandler_socket): Make wsock_evt public.
* fhandler_socket.cc (fhandler_socket::fhandler_socket): Accomodate
reordering members.
(fhandler_socket::evaluate_events): Drop FD_CONNECT event as soon as
it gets read once. Never remove FD_WRITE event here.
(fhandler_socket::wait_for_events): Wait 50 ms instead of INFINITE for
socket events.
(fhandler_socket::accept): Fix conditional. Set wsock_events members
of accepted socket to useful start values.
(fhandler_socket::recv_internal): Always drop FD_READ/FD_OOB events from
wsock_events after the call to WSARecvFrom.
(fhandler_socket::send_internal): Drop FD_WRITE event from wsock_events
if the call to WSASendTo fails with WSAEWOULDBLOCK. Fix return value
condition.
* select.cc (struct socketinf): Change to accomodate using socket event
handling.
(peek_socket): Use event handling for peeking socket.
(thread_socket): Ditto.
(start_thread_socket): Ditto.
(socket_cleanup): Same here.
* tlsoffsets.h: Regenerate.
2006-07-20 Corinna Vinschen <corinna@vinschen.de>
* fhandler.h (class fhandler_socket): Rearrange slightly to keep
event handling methods and members together. Drop owner status flag.
Split wait method. Rename event handling methods for readability.
* fhandler_socket.cc (struct wsa_event): Add owner field.
(LOCK_EVENTS): New macro.
(UNLOCK_EVENTS): Ditto.
(fhandler_socket::init_events): rename from prepare.
(fhandler_socket::evaluate_events): First half of former wait method.
Do everything but wait. Allow specifiying whether or not events from
event_mask should be erased from wsock_events->events. Simplify
OOB handling. Allow sending SIGURG to any process (group).
(fhandler_socket::wait_for_events): Second half of former wait method.
Call evaluate_events and wait in a loop if socket is blocking.
(fhandler_socket::release_events): Rename from release.
(fhandler_socket::connect): Accomodate above name changes.
(fhandler_socket::accept): Ditto.
(fhandler_socket::recv_internal): Ditto.
(fhandler_socket::send_internal): Ditto.
(fhandler_socket::close): Ditto.
(fhandler_socket::fcntl): Always set owner to given input value on
F_SETOWN. Handle F_GETOWN.
* net.cc (fdsock): Accomodate above name changes.
2006-07-20 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::wait): Set Winsock errno to
WSAEWOULDBLOCK instead of WSAEINPROGRESS.
2006-07-18 Brian Ford <Brian.Ford@FlightSafety.com>
Corinna Vinschen <corinna@vinschen.de>
* winsup.h (mmap_region_status): New enum.
(mmap_is_attached_or_noreserve_page): Adjust prototype and rename
as below.
* mmap.cc (mmap_is_attached_or_noreserve_page): Rename
mmap_is_attached_or_noreserve. Add region length parameter.
Return enum above.
* exceptions.cc (_cygtls::handle_exceptions): Accomodate above.
* fhandler.cc (fhandler_base::raw_read): Call above for NOACCESS
errors and retry on success to allow reads into untouched
MAP_NORESERVE buffers.
2006-07-18 Corinna Vinschen <corinna@vinschen.de>
* cygwin.din (posix_openpt): Export.
* tty.cc (posix_openpt): New function.
* include/cygwin/stdlib.h (posix_openpt): Declare.
* include/cygwin/version.h: Bump API minor number.
2006-07-14 Corinna Vinschen <corinna@vinschen.de>
* security.cc (get_token_group_sidlist): Always add the interactive
group to the token. Add comment. Create logon_id group SID by
copying it from incoming group list.
(create_token): Add subauth_token parameter. Use information in
subauth_token if present. Tweak SourceIdentifier if subauth_token
is present for debugging purposes.
* security.h (create_token): Add subauth_token parameter in declaration.
* syscalls.cc (seteuid32): Call subauth first. Call create_token
regardless. Use subauth token in call to create_token if subauth
succeeded.
2006-07-13 Corinna Vinschen <corinna@vinschen.de>
* include/netinet/in.h: Update copyright.
2006-07-13 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::wait): Rework function so that
WaitForMultipleObjects is really only called when necessary.
2006-07-12 Corinna Vinschen <corinna@vinschen.de>
* include/netdb.h: Declare rcmd, rcmd_af, rexec, rresvport,
rresvport_af, iruserok, iruserok_sa, ruserok.
2006-07-12 Corinna Vinschen <corinna@vinschen.de>
* Makefile.in (DLL_OFILES): Drop iruserok.o. Add rcmd.o.
* autoload.cc (rcmd): Drop definition.
* cygwin.din: Export bindresvport, bindresvport_sa, iruserok_sa,
rcmd_af, rresvport_af.
* net.cc (cygwin_rcmd): Remove.
(last_used_bindresvport): Rename from last_used_rrecvport.
(cygwin_bindresvport_sa): New function implementing bindresvport_sa.
(cygwin_bindresvport): New function implementing bindresvport.
(cygwin_rresvport): Remove.
* include/cygwin/version.h: Bump API minor number.
* include/netinet/in.h: Declare bindresvport and bindresvport_sa.
* libc/iruserok.c: Remove file.
* libc/rcmd.cc: New file implementing rcmd, rcmd_af, rresvport,
rresvport_af, iruserok_sa, iruserok and ruserok.
2006-07-12 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::getsockname): Return valid
result for unbound sockets.
2006-07-11 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::fixup_after_fork): Handle
wsock_mtx and wsock_evt on fork, thus handling close_on_exec correctly.
(fhandler_socket::fixup_after_exec): Drop misguided attempt to handle
close_on_exec here.
(fhandler_socket::dup): Call fixup_after_fork with NULL parent.
Add comment.
(fhandler_socket::set_close_on_exec): Handle wsock_mtx and wsock_evt.
2006-07-10 Corinna Vinschen <corinna@vinschen.de>
* fhandler.h (class fhandler_socket): Add wsock_mtx, wsock_evt
and wsock_events members. Remove closed status flag, add listener
status flag. Accomodate new implementation of socket event handling
methods. Declare recv* and send* functions ssize_t as the POSIX
equivalents.
(fhandler_socket::recv_internal): Declare.
(fhandler_socket::send_internal): Ditto.
* fhandler_socket.cc (EVENT_MASK): Define mask of selected events.
(fhandler_socket::fhandler_socket): Initialize new members.
(fhandler_socket::af_local_setblocking): Don't actually set the
socket to blocking mode. Keep sane event selection.
(fhandler_socket::af_local_unsetblocking): Don't actually set the
socket to previous blocking setting, just remember it.
(struct wsa_event): New structure to keep event data per shared
socket.
(NUM_SOCKS): Define number of shared sockets concurrently handled by
all active Cygwin processes.
(wsa_events): New shared datastructure keeping all wsa_event records.
(socket_serial_number): New shared variable to identify shared sockets.
(wsa_slot_mtx): Global mutex to serialize wsa_events access.
(search_wsa_event_slot): New static function to select a new wsa_event
slot for a new socket.
(fhandler_socket::prepare): Rewrite. Prepare event selection
per new socket.
(fhandler_socket::wait): Rewrite. Wait for socket events in thread
safe and multiple process safe.
(fhandler_socket::release): Rewrite. Close per-socket descriptor
mutex handle and event handle.
(fhandler_socket::dup): Duplicate wsock_mtx and wsock_evt. Fix
copy-paste error in debug output.
(fhandler_socket::connect): Accomodate new event handling.
(fhandler_socket::listen): Set listener flag on successful listen.
(fhandler_socket::accept): Accomodate new event handling.
(fhandler_socket::recv_internal): New inline method centralizing
common recv code.
(fhandler_socket::recvfrom): Call recv_internal now.
(fhandler_socket::recvmsg): Ditto. Streamline copying from iovec
to WSABUF.
(fhandler_socket::send_internal): New inline method centralizing
common send code.
(fhandler_socket::sendto): Call send_internal now.
(fhandler_socket::sendmsg): Ditto. Streamline copying from iovec
to WSABUF.
(fhandler_socket::close): Call release now.
(fhandler_socket::ioctl): Never actually switch to blocking mode.
Just keep track of the setting.
* net.cc (fdsock): Call prepare now.
(cygwin_connect): Revert again to event driven technique.
(cygwin_accept): Ditto.
* poll.cc (poll): Don't call recvfrom on a listening socket.
Remove special case for failing recvfrom.
* include/sys/socket.h: Declare recv* and send* functions ssize_t as
requested by POSIX.
2006-07-07 Corinna Vinschen <corinna@vinschen.de>
* net.cc (cygwin_inet_ntop): Fix data type of forth parameter.
2006-07-06 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/in6.h (struct in6_addr): Fix typo.
2006-07-06 Corinna Vinschen <corinna@vinschen.de>
* cygwin.din: Export in6addr_any, in6addr_loopback, freeaddrinfo,
gai_strerror, getaddrinfo, getnameinfo.
* fhandler_socket.cc: Include cygwin/in6.h.
(get_inet_addr): Accomodate AF_INET6 usage.
(fhandler_socket::connect): Ditto.
(fhandler_socket::listen): Ditto.
(fhandler_socket::sendto): Ditto.
* net.cc: Include cygwin/in6.h.
(in6addr_any): Define.
(in6addr_loopback): Define.
(cygwin_socket): Accomodate AF_INET6 usage.
(socketpair): Bind socketpairs only to loopback for security.
(inet_pton4): New static function.
(inet_pton6): Ditto.
(cygwin_inet_pton): New AF_INET6 aware inet_pton implementation.
(inet_ntop4): New static function.
(inet_ntop6): Ditto.
(cygwin_inet_ntop): New AF_INET6 aware inet_ntop implementation.
(ga_aistruct): New static function.
(ga_clone): Ditto.
(ga_echeck): Ditto.
(ga_nsearch): Ditto.
(ga_port): Ditto.
(ga_serv): Ditto.
(ga_unix): Ditto.
(gn_ipv46): Ditto.
(ipv4_freeaddrinfo): Ditto.
(ipv4_getaddrinfo): Ditto.
(ipv4_getnameinfo): Ditto.
(gai_errmap_t): New structure holding error code - error string mapping.
(cygwin_gai_strerror): New function implementing gai_strerror.
(w32_to_gai_err): New static function.
(get_ipv6_funcs): Ditto.
(load_ipv6_funcs): Ditto.
(cygwin_freeaddrinfo): New function implementing freeaddrinfo.
(cygwin_getaddrinfo): New function implementing getaddrinfo.
(cygwin_getnameinfo): New function implementing getnameinfo.
* include/netdb.h: Include stdint.h and cygwin/socket.h. Define
data types and macros used by getaddrinfo and friends. Declare
freeaddrinfo, gai_strerror, getaddrinfo and getnameinfo.
* include/cygwin/in.h: Add IPv6 related IPPROTOs. Remove definition
of struct sockaddr_in6. Include cygwin/in6.h instead.
* include/cygwin/in6.h: New header file defining IPv6 releated
data types and macros.
* include/cygwin/socket.h: Enable AF_INET6 and PF_INET6. Add
IPv6 related socket options.
* include/cygwin/version.h: Bump API minor number.
2006-07-06 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (DsGetDcNameA): Define.
(NetGetAnyDCName): Define.
* security.cc: Include dsgetdc.h.
(DsGetDcNameA): Declare.
(DS_FORCE_REDISCOVERY): Define.
(get_logon_server): Add bool parameter to control rediscovery of DC.
Use DsGetDcNameA function if supported, NetGetDCName/NetGetAnyDCName
otherwise.
(get_server_groups): Rediscover DC if get_user_groups fails and
try again.
(get_reg_security): Use correct error code macro when testing
RegGetKeySecurity return value.
* security.h (get_logon_server): Remove default vaue from wserver
parameter. Add rediscovery parameter.
* uinfo.cc (cygheap_user::env_logsrv): Accomodate rediscovery parameter
in call to get_logon_server.
2006-07-26 03:23:23 +08:00
|
|
|
switch (mmap_is_attached_or_noreserve ((void *)e->ExceptionInformation[1],
|
|
|
|
1))
|
2007-02-20 08:16:18 +08:00
|
|
|
{
|
2006-07-25 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/version.h: Bump DLL version to 1.7.0.
2006-07-25 Corinna Vinschen <corinna@vinschen.de>
* select.h: Remove.
* fhandler_socket.cc: Don't include select.h.
* select.cc: Ditto.
2006-07-25 Corinna Vinschen <corinna@vinschen.de>
* cygtls.h: Drop socket related includes.
(struct _local_storage): Remove exitsock and exitsock_sin. Add
select_sockevt.
* cygtls.cc: Accomodate above change throughout.
* fhandler.h (class fhandler_socket): Make wsock_evt public.
* fhandler_socket.cc (fhandler_socket::fhandler_socket): Accomodate
reordering members.
(fhandler_socket::evaluate_events): Drop FD_CONNECT event as soon as
it gets read once. Never remove FD_WRITE event here.
(fhandler_socket::wait_for_events): Wait 50 ms instead of INFINITE for
socket events.
(fhandler_socket::accept): Fix conditional. Set wsock_events members
of accepted socket to useful start values.
(fhandler_socket::recv_internal): Always drop FD_READ/FD_OOB events from
wsock_events after the call to WSARecvFrom.
(fhandler_socket::send_internal): Drop FD_WRITE event from wsock_events
if the call to WSASendTo fails with WSAEWOULDBLOCK. Fix return value
condition.
* select.cc (struct socketinf): Change to accomodate using socket event
handling.
(peek_socket): Use event handling for peeking socket.
(thread_socket): Ditto.
(start_thread_socket): Ditto.
(socket_cleanup): Same here.
* tlsoffsets.h: Regenerate.
2006-07-20 Corinna Vinschen <corinna@vinschen.de>
* fhandler.h (class fhandler_socket): Rearrange slightly to keep
event handling methods and members together. Drop owner status flag.
Split wait method. Rename event handling methods for readability.
* fhandler_socket.cc (struct wsa_event): Add owner field.
(LOCK_EVENTS): New macro.
(UNLOCK_EVENTS): Ditto.
(fhandler_socket::init_events): rename from prepare.
(fhandler_socket::evaluate_events): First half of former wait method.
Do everything but wait. Allow specifiying whether or not events from
event_mask should be erased from wsock_events->events. Simplify
OOB handling. Allow sending SIGURG to any process (group).
(fhandler_socket::wait_for_events): Second half of former wait method.
Call evaluate_events and wait in a loop if socket is blocking.
(fhandler_socket::release_events): Rename from release.
(fhandler_socket::connect): Accomodate above name changes.
(fhandler_socket::accept): Ditto.
(fhandler_socket::recv_internal): Ditto.
(fhandler_socket::send_internal): Ditto.
(fhandler_socket::close): Ditto.
(fhandler_socket::fcntl): Always set owner to given input value on
F_SETOWN. Handle F_GETOWN.
* net.cc (fdsock): Accomodate above name changes.
2006-07-20 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::wait): Set Winsock errno to
WSAEWOULDBLOCK instead of WSAEINPROGRESS.
2006-07-18 Brian Ford <Brian.Ford@FlightSafety.com>
Corinna Vinschen <corinna@vinschen.de>
* winsup.h (mmap_region_status): New enum.
(mmap_is_attached_or_noreserve_page): Adjust prototype and rename
as below.
* mmap.cc (mmap_is_attached_or_noreserve_page): Rename
mmap_is_attached_or_noreserve. Add region length parameter.
Return enum above.
* exceptions.cc (_cygtls::handle_exceptions): Accomodate above.
* fhandler.cc (fhandler_base::raw_read): Call above for NOACCESS
errors and retry on success to allow reads into untouched
MAP_NORESERVE buffers.
2006-07-18 Corinna Vinschen <corinna@vinschen.de>
* cygwin.din (posix_openpt): Export.
* tty.cc (posix_openpt): New function.
* include/cygwin/stdlib.h (posix_openpt): Declare.
* include/cygwin/version.h: Bump API minor number.
2006-07-14 Corinna Vinschen <corinna@vinschen.de>
* security.cc (get_token_group_sidlist): Always add the interactive
group to the token. Add comment. Create logon_id group SID by
copying it from incoming group list.
(create_token): Add subauth_token parameter. Use information in
subauth_token if present. Tweak SourceIdentifier if subauth_token
is present for debugging purposes.
* security.h (create_token): Add subauth_token parameter in declaration.
* syscalls.cc (seteuid32): Call subauth first. Call create_token
regardless. Use subauth token in call to create_token if subauth
succeeded.
2006-07-13 Corinna Vinschen <corinna@vinschen.de>
* include/netinet/in.h: Update copyright.
2006-07-13 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::wait): Rework function so that
WaitForMultipleObjects is really only called when necessary.
2006-07-12 Corinna Vinschen <corinna@vinschen.de>
* include/netdb.h: Declare rcmd, rcmd_af, rexec, rresvport,
rresvport_af, iruserok, iruserok_sa, ruserok.
2006-07-12 Corinna Vinschen <corinna@vinschen.de>
* Makefile.in (DLL_OFILES): Drop iruserok.o. Add rcmd.o.
* autoload.cc (rcmd): Drop definition.
* cygwin.din: Export bindresvport, bindresvport_sa, iruserok_sa,
rcmd_af, rresvport_af.
* net.cc (cygwin_rcmd): Remove.
(last_used_bindresvport): Rename from last_used_rrecvport.
(cygwin_bindresvport_sa): New function implementing bindresvport_sa.
(cygwin_bindresvport): New function implementing bindresvport.
(cygwin_rresvport): Remove.
* include/cygwin/version.h: Bump API minor number.
* include/netinet/in.h: Declare bindresvport and bindresvport_sa.
* libc/iruserok.c: Remove file.
* libc/rcmd.cc: New file implementing rcmd, rcmd_af, rresvport,
rresvport_af, iruserok_sa, iruserok and ruserok.
2006-07-12 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::getsockname): Return valid
result for unbound sockets.
2006-07-11 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::fixup_after_fork): Handle
wsock_mtx and wsock_evt on fork, thus handling close_on_exec correctly.
(fhandler_socket::fixup_after_exec): Drop misguided attempt to handle
close_on_exec here.
(fhandler_socket::dup): Call fixup_after_fork with NULL parent.
Add comment.
(fhandler_socket::set_close_on_exec): Handle wsock_mtx and wsock_evt.
2006-07-10 Corinna Vinschen <corinna@vinschen.de>
* fhandler.h (class fhandler_socket): Add wsock_mtx, wsock_evt
and wsock_events members. Remove closed status flag, add listener
status flag. Accomodate new implementation of socket event handling
methods. Declare recv* and send* functions ssize_t as the POSIX
equivalents.
(fhandler_socket::recv_internal): Declare.
(fhandler_socket::send_internal): Ditto.
* fhandler_socket.cc (EVENT_MASK): Define mask of selected events.
(fhandler_socket::fhandler_socket): Initialize new members.
(fhandler_socket::af_local_setblocking): Don't actually set the
socket to blocking mode. Keep sane event selection.
(fhandler_socket::af_local_unsetblocking): Don't actually set the
socket to previous blocking setting, just remember it.
(struct wsa_event): New structure to keep event data per shared
socket.
(NUM_SOCKS): Define number of shared sockets concurrently handled by
all active Cygwin processes.
(wsa_events): New shared datastructure keeping all wsa_event records.
(socket_serial_number): New shared variable to identify shared sockets.
(wsa_slot_mtx): Global mutex to serialize wsa_events access.
(search_wsa_event_slot): New static function to select a new wsa_event
slot for a new socket.
(fhandler_socket::prepare): Rewrite. Prepare event selection
per new socket.
(fhandler_socket::wait): Rewrite. Wait for socket events in thread
safe and multiple process safe.
(fhandler_socket::release): Rewrite. Close per-socket descriptor
mutex handle and event handle.
(fhandler_socket::dup): Duplicate wsock_mtx and wsock_evt. Fix
copy-paste error in debug output.
(fhandler_socket::connect): Accomodate new event handling.
(fhandler_socket::listen): Set listener flag on successful listen.
(fhandler_socket::accept): Accomodate new event handling.
(fhandler_socket::recv_internal): New inline method centralizing
common recv code.
(fhandler_socket::recvfrom): Call recv_internal now.
(fhandler_socket::recvmsg): Ditto. Streamline copying from iovec
to WSABUF.
(fhandler_socket::send_internal): New inline method centralizing
common send code.
(fhandler_socket::sendto): Call send_internal now.
(fhandler_socket::sendmsg): Ditto. Streamline copying from iovec
to WSABUF.
(fhandler_socket::close): Call release now.
(fhandler_socket::ioctl): Never actually switch to blocking mode.
Just keep track of the setting.
* net.cc (fdsock): Call prepare now.
(cygwin_connect): Revert again to event driven technique.
(cygwin_accept): Ditto.
* poll.cc (poll): Don't call recvfrom on a listening socket.
Remove special case for failing recvfrom.
* include/sys/socket.h: Declare recv* and send* functions ssize_t as
requested by POSIX.
2006-07-07 Corinna Vinschen <corinna@vinschen.de>
* net.cc (cygwin_inet_ntop): Fix data type of forth parameter.
2006-07-06 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/in6.h (struct in6_addr): Fix typo.
2006-07-06 Corinna Vinschen <corinna@vinschen.de>
* cygwin.din: Export in6addr_any, in6addr_loopback, freeaddrinfo,
gai_strerror, getaddrinfo, getnameinfo.
* fhandler_socket.cc: Include cygwin/in6.h.
(get_inet_addr): Accomodate AF_INET6 usage.
(fhandler_socket::connect): Ditto.
(fhandler_socket::listen): Ditto.
(fhandler_socket::sendto): Ditto.
* net.cc: Include cygwin/in6.h.
(in6addr_any): Define.
(in6addr_loopback): Define.
(cygwin_socket): Accomodate AF_INET6 usage.
(socketpair): Bind socketpairs only to loopback for security.
(inet_pton4): New static function.
(inet_pton6): Ditto.
(cygwin_inet_pton): New AF_INET6 aware inet_pton implementation.
(inet_ntop4): New static function.
(inet_ntop6): Ditto.
(cygwin_inet_ntop): New AF_INET6 aware inet_ntop implementation.
(ga_aistruct): New static function.
(ga_clone): Ditto.
(ga_echeck): Ditto.
(ga_nsearch): Ditto.
(ga_port): Ditto.
(ga_serv): Ditto.
(ga_unix): Ditto.
(gn_ipv46): Ditto.
(ipv4_freeaddrinfo): Ditto.
(ipv4_getaddrinfo): Ditto.
(ipv4_getnameinfo): Ditto.
(gai_errmap_t): New structure holding error code - error string mapping.
(cygwin_gai_strerror): New function implementing gai_strerror.
(w32_to_gai_err): New static function.
(get_ipv6_funcs): Ditto.
(load_ipv6_funcs): Ditto.
(cygwin_freeaddrinfo): New function implementing freeaddrinfo.
(cygwin_getaddrinfo): New function implementing getaddrinfo.
(cygwin_getnameinfo): New function implementing getnameinfo.
* include/netdb.h: Include stdint.h and cygwin/socket.h. Define
data types and macros used by getaddrinfo and friends. Declare
freeaddrinfo, gai_strerror, getaddrinfo and getnameinfo.
* include/cygwin/in.h: Add IPv6 related IPPROTOs. Remove definition
of struct sockaddr_in6. Include cygwin/in6.h instead.
* include/cygwin/in6.h: New header file defining IPv6 releated
data types and macros.
* include/cygwin/socket.h: Enable AF_INET6 and PF_INET6. Add
IPv6 related socket options.
* include/cygwin/version.h: Bump API minor number.
2006-07-06 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (DsGetDcNameA): Define.
(NetGetAnyDCName): Define.
* security.cc: Include dsgetdc.h.
(DsGetDcNameA): Declare.
(DS_FORCE_REDISCOVERY): Define.
(get_logon_server): Add bool parameter to control rediscovery of DC.
Use DsGetDcNameA function if supported, NetGetDCName/NetGetAnyDCName
otherwise.
(get_server_groups): Rediscover DC if get_user_groups fails and
try again.
(get_reg_security): Use correct error code macro when testing
RegGetKeySecurity return value.
* security.h (get_logon_server): Remove default vaue from wserver
parameter. Add rediscovery parameter.
* uinfo.cc (cygheap_user::env_logsrv): Accomodate rediscovery parameter
in call to get_logon_server.
2006-07-26 03:23:23 +08:00
|
|
|
case MMAP_NORESERVE_COMMITED:
|
2014-03-29 06:31:53 +08:00
|
|
|
return ExceptionContinueExecution;
|
2006-07-25 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/version.h: Bump DLL version to 1.7.0.
2006-07-25 Corinna Vinschen <corinna@vinschen.de>
* select.h: Remove.
* fhandler_socket.cc: Don't include select.h.
* select.cc: Ditto.
2006-07-25 Corinna Vinschen <corinna@vinschen.de>
* cygtls.h: Drop socket related includes.
(struct _local_storage): Remove exitsock and exitsock_sin. Add
select_sockevt.
* cygtls.cc: Accomodate above change throughout.
* fhandler.h (class fhandler_socket): Make wsock_evt public.
* fhandler_socket.cc (fhandler_socket::fhandler_socket): Accomodate
reordering members.
(fhandler_socket::evaluate_events): Drop FD_CONNECT event as soon as
it gets read once. Never remove FD_WRITE event here.
(fhandler_socket::wait_for_events): Wait 50 ms instead of INFINITE for
socket events.
(fhandler_socket::accept): Fix conditional. Set wsock_events members
of accepted socket to useful start values.
(fhandler_socket::recv_internal): Always drop FD_READ/FD_OOB events from
wsock_events after the call to WSARecvFrom.
(fhandler_socket::send_internal): Drop FD_WRITE event from wsock_events
if the call to WSASendTo fails with WSAEWOULDBLOCK. Fix return value
condition.
* select.cc (struct socketinf): Change to accomodate using socket event
handling.
(peek_socket): Use event handling for peeking socket.
(thread_socket): Ditto.
(start_thread_socket): Ditto.
(socket_cleanup): Same here.
* tlsoffsets.h: Regenerate.
2006-07-20 Corinna Vinschen <corinna@vinschen.de>
* fhandler.h (class fhandler_socket): Rearrange slightly to keep
event handling methods and members together. Drop owner status flag.
Split wait method. Rename event handling methods for readability.
* fhandler_socket.cc (struct wsa_event): Add owner field.
(LOCK_EVENTS): New macro.
(UNLOCK_EVENTS): Ditto.
(fhandler_socket::init_events): rename from prepare.
(fhandler_socket::evaluate_events): First half of former wait method.
Do everything but wait. Allow specifiying whether or not events from
event_mask should be erased from wsock_events->events. Simplify
OOB handling. Allow sending SIGURG to any process (group).
(fhandler_socket::wait_for_events): Second half of former wait method.
Call evaluate_events and wait in a loop if socket is blocking.
(fhandler_socket::release_events): Rename from release.
(fhandler_socket::connect): Accomodate above name changes.
(fhandler_socket::accept): Ditto.
(fhandler_socket::recv_internal): Ditto.
(fhandler_socket::send_internal): Ditto.
(fhandler_socket::close): Ditto.
(fhandler_socket::fcntl): Always set owner to given input value on
F_SETOWN. Handle F_GETOWN.
* net.cc (fdsock): Accomodate above name changes.
2006-07-20 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::wait): Set Winsock errno to
WSAEWOULDBLOCK instead of WSAEINPROGRESS.
2006-07-18 Brian Ford <Brian.Ford@FlightSafety.com>
Corinna Vinschen <corinna@vinschen.de>
* winsup.h (mmap_region_status): New enum.
(mmap_is_attached_or_noreserve_page): Adjust prototype and rename
as below.
* mmap.cc (mmap_is_attached_or_noreserve_page): Rename
mmap_is_attached_or_noreserve. Add region length parameter.
Return enum above.
* exceptions.cc (_cygtls::handle_exceptions): Accomodate above.
* fhandler.cc (fhandler_base::raw_read): Call above for NOACCESS
errors and retry on success to allow reads into untouched
MAP_NORESERVE buffers.
2006-07-18 Corinna Vinschen <corinna@vinschen.de>
* cygwin.din (posix_openpt): Export.
* tty.cc (posix_openpt): New function.
* include/cygwin/stdlib.h (posix_openpt): Declare.
* include/cygwin/version.h: Bump API minor number.
2006-07-14 Corinna Vinschen <corinna@vinschen.de>
* security.cc (get_token_group_sidlist): Always add the interactive
group to the token. Add comment. Create logon_id group SID by
copying it from incoming group list.
(create_token): Add subauth_token parameter. Use information in
subauth_token if present. Tweak SourceIdentifier if subauth_token
is present for debugging purposes.
* security.h (create_token): Add subauth_token parameter in declaration.
* syscalls.cc (seteuid32): Call subauth first. Call create_token
regardless. Use subauth token in call to create_token if subauth
succeeded.
2006-07-13 Corinna Vinschen <corinna@vinschen.de>
* include/netinet/in.h: Update copyright.
2006-07-13 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::wait): Rework function so that
WaitForMultipleObjects is really only called when necessary.
2006-07-12 Corinna Vinschen <corinna@vinschen.de>
* include/netdb.h: Declare rcmd, rcmd_af, rexec, rresvport,
rresvport_af, iruserok, iruserok_sa, ruserok.
2006-07-12 Corinna Vinschen <corinna@vinschen.de>
* Makefile.in (DLL_OFILES): Drop iruserok.o. Add rcmd.o.
* autoload.cc (rcmd): Drop definition.
* cygwin.din: Export bindresvport, bindresvport_sa, iruserok_sa,
rcmd_af, rresvport_af.
* net.cc (cygwin_rcmd): Remove.
(last_used_bindresvport): Rename from last_used_rrecvport.
(cygwin_bindresvport_sa): New function implementing bindresvport_sa.
(cygwin_bindresvport): New function implementing bindresvport.
(cygwin_rresvport): Remove.
* include/cygwin/version.h: Bump API minor number.
* include/netinet/in.h: Declare bindresvport and bindresvport_sa.
* libc/iruserok.c: Remove file.
* libc/rcmd.cc: New file implementing rcmd, rcmd_af, rresvport,
rresvport_af, iruserok_sa, iruserok and ruserok.
2006-07-12 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::getsockname): Return valid
result for unbound sockets.
2006-07-11 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::fixup_after_fork): Handle
wsock_mtx and wsock_evt on fork, thus handling close_on_exec correctly.
(fhandler_socket::fixup_after_exec): Drop misguided attempt to handle
close_on_exec here.
(fhandler_socket::dup): Call fixup_after_fork with NULL parent.
Add comment.
(fhandler_socket::set_close_on_exec): Handle wsock_mtx and wsock_evt.
2006-07-10 Corinna Vinschen <corinna@vinschen.de>
* fhandler.h (class fhandler_socket): Add wsock_mtx, wsock_evt
and wsock_events members. Remove closed status flag, add listener
status flag. Accomodate new implementation of socket event handling
methods. Declare recv* and send* functions ssize_t as the POSIX
equivalents.
(fhandler_socket::recv_internal): Declare.
(fhandler_socket::send_internal): Ditto.
* fhandler_socket.cc (EVENT_MASK): Define mask of selected events.
(fhandler_socket::fhandler_socket): Initialize new members.
(fhandler_socket::af_local_setblocking): Don't actually set the
socket to blocking mode. Keep sane event selection.
(fhandler_socket::af_local_unsetblocking): Don't actually set the
socket to previous blocking setting, just remember it.
(struct wsa_event): New structure to keep event data per shared
socket.
(NUM_SOCKS): Define number of shared sockets concurrently handled by
all active Cygwin processes.
(wsa_events): New shared datastructure keeping all wsa_event records.
(socket_serial_number): New shared variable to identify shared sockets.
(wsa_slot_mtx): Global mutex to serialize wsa_events access.
(search_wsa_event_slot): New static function to select a new wsa_event
slot for a new socket.
(fhandler_socket::prepare): Rewrite. Prepare event selection
per new socket.
(fhandler_socket::wait): Rewrite. Wait for socket events in thread
safe and multiple process safe.
(fhandler_socket::release): Rewrite. Close per-socket descriptor
mutex handle and event handle.
(fhandler_socket::dup): Duplicate wsock_mtx and wsock_evt. Fix
copy-paste error in debug output.
(fhandler_socket::connect): Accomodate new event handling.
(fhandler_socket::listen): Set listener flag on successful listen.
(fhandler_socket::accept): Accomodate new event handling.
(fhandler_socket::recv_internal): New inline method centralizing
common recv code.
(fhandler_socket::recvfrom): Call recv_internal now.
(fhandler_socket::recvmsg): Ditto. Streamline copying from iovec
to WSABUF.
(fhandler_socket::send_internal): New inline method centralizing
common send code.
(fhandler_socket::sendto): Call send_internal now.
(fhandler_socket::sendmsg): Ditto. Streamline copying from iovec
to WSABUF.
(fhandler_socket::close): Call release now.
(fhandler_socket::ioctl): Never actually switch to blocking mode.
Just keep track of the setting.
* net.cc (fdsock): Call prepare now.
(cygwin_connect): Revert again to event driven technique.
(cygwin_accept): Ditto.
* poll.cc (poll): Don't call recvfrom on a listening socket.
Remove special case for failing recvfrom.
* include/sys/socket.h: Declare recv* and send* functions ssize_t as
requested by POSIX.
2006-07-07 Corinna Vinschen <corinna@vinschen.de>
* net.cc (cygwin_inet_ntop): Fix data type of forth parameter.
2006-07-06 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/in6.h (struct in6_addr): Fix typo.
2006-07-06 Corinna Vinschen <corinna@vinschen.de>
* cygwin.din: Export in6addr_any, in6addr_loopback, freeaddrinfo,
gai_strerror, getaddrinfo, getnameinfo.
* fhandler_socket.cc: Include cygwin/in6.h.
(get_inet_addr): Accomodate AF_INET6 usage.
(fhandler_socket::connect): Ditto.
(fhandler_socket::listen): Ditto.
(fhandler_socket::sendto): Ditto.
* net.cc: Include cygwin/in6.h.
(in6addr_any): Define.
(in6addr_loopback): Define.
(cygwin_socket): Accomodate AF_INET6 usage.
(socketpair): Bind socketpairs only to loopback for security.
(inet_pton4): New static function.
(inet_pton6): Ditto.
(cygwin_inet_pton): New AF_INET6 aware inet_pton implementation.
(inet_ntop4): New static function.
(inet_ntop6): Ditto.
(cygwin_inet_ntop): New AF_INET6 aware inet_ntop implementation.
(ga_aistruct): New static function.
(ga_clone): Ditto.
(ga_echeck): Ditto.
(ga_nsearch): Ditto.
(ga_port): Ditto.
(ga_serv): Ditto.
(ga_unix): Ditto.
(gn_ipv46): Ditto.
(ipv4_freeaddrinfo): Ditto.
(ipv4_getaddrinfo): Ditto.
(ipv4_getnameinfo): Ditto.
(gai_errmap_t): New structure holding error code - error string mapping.
(cygwin_gai_strerror): New function implementing gai_strerror.
(w32_to_gai_err): New static function.
(get_ipv6_funcs): Ditto.
(load_ipv6_funcs): Ditto.
(cygwin_freeaddrinfo): New function implementing freeaddrinfo.
(cygwin_getaddrinfo): New function implementing getaddrinfo.
(cygwin_getnameinfo): New function implementing getnameinfo.
* include/netdb.h: Include stdint.h and cygwin/socket.h. Define
data types and macros used by getaddrinfo and friends. Declare
freeaddrinfo, gai_strerror, getaddrinfo and getnameinfo.
* include/cygwin/in.h: Add IPv6 related IPPROTOs. Remove definition
of struct sockaddr_in6. Include cygwin/in6.h instead.
* include/cygwin/in6.h: New header file defining IPv6 releated
data types and macros.
* include/cygwin/socket.h: Enable AF_INET6 and PF_INET6. Add
IPv6 related socket options.
* include/cygwin/version.h: Bump API minor number.
2006-07-06 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (DsGetDcNameA): Define.
(NetGetAnyDCName): Define.
* security.cc: Include dsgetdc.h.
(DsGetDcNameA): Declare.
(DS_FORCE_REDISCOVERY): Define.
(get_logon_server): Add bool parameter to control rediscovery of DC.
Use DsGetDcNameA function if supported, NetGetDCName/NetGetAnyDCName
otherwise.
(get_server_groups): Rediscover DC if get_user_groups fails and
try again.
(get_reg_security): Use correct error code macro when testing
RegGetKeySecurity return value.
* security.h (get_logon_server): Remove default vaue from wserver
parameter. Add rediscovery parameter.
* uinfo.cc (cygheap_user::env_logsrv): Accomodate rediscovery parameter
in call to get_logon_server.
2006-07-26 03:23:23 +08:00
|
|
|
case MMAP_RAISE_SIGBUS: /* MAP_NORESERVE page, commit failed, or
|
|
|
|
access to mmap page beyond EOF. */
|
2005-12-07 19:16:47 +08:00
|
|
|
si.si_signo = SIGBUS;
|
|
|
|
si.si_code = BUS_OBJERR;
|
2006-07-13 16:33:34 +08:00
|
|
|
break;
|
|
|
|
default:
|
2005-12-28 04:07:59 +08:00
|
|
|
MEMORY_BASIC_INFORMATION m;
|
|
|
|
VirtualQuery ((PVOID) e->ExceptionInformation[1], &m, sizeof m);
|
|
|
|
si.si_signo = SIGSEGV;
|
|
|
|
si.si_code = m.State == MEM_FREE ? SEGV_MAPERR : SEGV_ACCERR;
|
2006-07-13 16:33:34 +08:00
|
|
|
break;
|
2005-12-28 04:07:59 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2015-06-19 21:58:23 +08:00
|
|
|
case STATUS_STACK_OVERFLOW:
|
|
|
|
/* If we encounter a stack overflow, and if the thread has no alternate
|
|
|
|
stack, don't even try to call a signal handler. This is in line with
|
|
|
|
Linux behaviour and also makes a lot of sense on Windows. */
|
|
|
|
if (me.altstack.ss_flags)
|
|
|
|
global_sigs[SIGSEGV].sa_handler = SIG_DFL;
|
2020-08-06 03:58:22 +08:00
|
|
|
fallthrough;
|
2000-02-18 03:38:33 +08:00
|
|
|
case STATUS_ARRAY_BOUNDS_EXCEEDED:
|
|
|
|
case STATUS_IN_PAGE_ERROR:
|
|
|
|
case STATUS_NO_MEMORY:
|
|
|
|
case STATUS_INVALID_DISPOSITION:
|
2004-01-19 13:46:54 +08:00
|
|
|
si.si_signo = SIGSEGV;
|
2005-09-26 21:23:47 +08:00
|
|
|
si.si_code = SEGV_MAPERR;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATUS_CONTROL_C_EXIT:
|
2004-01-19 13:46:54 +08:00
|
|
|
si.si_signo = SIGINT;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STATUS_INVALID_HANDLE:
|
|
|
|
/* CloseHandle will throw this exception if it is given an
|
|
|
|
invalid handle. We don't care about the exception; we just
|
|
|
|
want CloseHandle to return an error. This can be revisited
|
|
|
|
if gcc ever supports Windows style structured exception
|
|
|
|
handling. */
|
2014-03-29 06:31:53 +08:00
|
|
|
return ExceptionContinueExecution;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2020-08-18 04:24:59 +08:00
|
|
|
case STATUS_GCC_THROW:
|
|
|
|
case STATUS_GCC_UNWIND:
|
|
|
|
case STATUS_GCC_FORCED:
|
|
|
|
/* According to a comment in the GCC function
|
|
|
|
_Unwind_RaiseException(), GCC expects us to continue all the
|
|
|
|
(continuable) GCC exceptions that reach us. */
|
|
|
|
return ExceptionContinueExecution;
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
default:
|
|
|
|
/* If we don't recognize the exception, we have to assume that
|
|
|
|
we are doing structured exception handling, and we let
|
|
|
|
something else handle it. */
|
2014-03-29 06:31:53 +08:00
|
|
|
return ExceptionContinueSearch;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2015-06-19 22:12:10 +08:00
|
|
|
debug_printf ("In cygwin_except_handler exception %y at %p sp %p",
|
2022-05-17 20:12:32 +08:00
|
|
|
e->ExceptionCode, in->_CX_instPtr, in->_CX_stackPtr);
|
2015-06-19 22:12:10 +08:00
|
|
|
debug_printf ("In cygwin_except_handler signal %d at %p",
|
2022-05-17 20:12:32 +08:00
|
|
|
si.si_signo, in->_CX_instPtr);
|
2013-04-23 17:44:36 +08:00
|
|
|
|
2022-05-17 20:12:32 +08:00
|
|
|
PUINT_PTR framep = (PUINT_PTR) in->_CX_framePtr;
|
|
|
|
/* Sometimes, when a stack is screwed up, the frame pointer tends to be NULL.
|
|
|
|
In that case, base the stacktrace on the stack pointer. In most cases,
|
|
|
|
it allows to generate useful stack trace. */
|
2013-04-23 17:44:36 +08:00
|
|
|
if (!framep)
|
2022-05-17 20:12:32 +08:00
|
|
|
framep = (PUINT_PTR) in->_CX_stackPtr;
|
2008-03-03 06:51:19 +08:00
|
|
|
|
2013-03-01 23:48:14 +08:00
|
|
|
if (exit_state >= ES_SIGNAL_EXIT
|
|
|
|
&& (NTSTATUS) e->ExceptionCode != STATUS_CONTROL_C_EXIT)
|
|
|
|
api_fatal ("Exception during process exit");
|
2022-05-17 20:12:32 +08:00
|
|
|
else if (try_to_debug ())
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2016-02-13 01:17:35 +08:00
|
|
|
debugging = 1;
|
2014-03-29 06:31:53 +08:00
|
|
|
return ExceptionContinueExecution;
|
2013-01-03 02:34:06 +08:00
|
|
|
}
|
2005-12-28 04:07:59 +08:00
|
|
|
|
2013-04-23 17:44:36 +08:00
|
|
|
cygwin_exception exc (framep, in, e);
|
2013-01-03 02:34:06 +08:00
|
|
|
si.si_cyg = (void *) &exc;
|
2013-06-08 00:05:12 +08:00
|
|
|
/* POSIX requires that for SIGSEGV and SIGBUS, si_addr should be set to the
|
|
|
|
address of faulting memory reference. For SIGILL and SIGFPE these should
|
|
|
|
be the address of the faulting instruction. Other signals are apparently
|
2020-03-11 20:36:41 +08:00
|
|
|
undefined so we just set those to the faulting instruction too. */
|
2013-06-02 17:11:09 +08:00
|
|
|
si.si_addr = (si.si_signo == SIGSEGV || si.si_signo == SIGBUS)
|
2022-05-17 20:12:32 +08:00
|
|
|
? (void *) e->ExceptionInformation[1] : (void *) in->_CX_instPtr;
|
2005-12-06 04:20:18 +08:00
|
|
|
me.incyg++;
|
2013-01-03 02:34:06 +08:00
|
|
|
sig_send (NULL, si, &me); /* Signal myself */
|
2015-07-05 04:49:30 +08:00
|
|
|
if ((NTSTATUS) e->ExceptionCode == STATUS_STACK_OVERFLOW)
|
|
|
|
{
|
|
|
|
/* If we catched a stack overflow, and if the signal handler didn't exit
|
|
|
|
or longjmp, we're back here and about to continue, supposed to run the
|
|
|
|
offending instruction again. That works on Linux, but not on Windows.
|
|
|
|
In case of a stack overflow we're not immediately returning to the
|
|
|
|
system exception handler, but to NTDLL::__stkchk. __stkchk will then
|
|
|
|
terminate the applicaton. So what we do here is to signal our current
|
|
|
|
process again, but this time with SIG_DFL action. This creates a
|
|
|
|
stackdump and then exits through our own means. */
|
|
|
|
global_sigs[SIGSEGV].sa_handler = SIG_DFL;
|
|
|
|
sig_send (NULL, si, &me);
|
|
|
|
}
|
2005-12-06 04:20:18 +08:00
|
|
|
me.incyg--;
|
2005-12-03 12:23:35 +08:00
|
|
|
e->ExceptionFlags = 0;
|
2014-03-29 06:31:53 +08:00
|
|
|
return ExceptionContinueExecution;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Utilities to call a user supplied exception handler. */
|
|
|
|
|
2001-01-08 12:02:02 +08:00
|
|
|
#define SIG_NONMASKABLE (SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
/* Non-raceable sigsuspend
|
2013-06-08 00:05:12 +08:00
|
|
|
Note: This implementation is based on the Single UNIX Specification
|
|
|
|
man page. This indicates that sigsuspend always returns -1 and that
|
|
|
|
attempts to block unblockable signals will be silently ignored.
|
|
|
|
This is counter to what appears to be documented in some UNIX
|
|
|
|
man pages, e.g. Linux. */
|
2022-06-07 00:00:45 +08:00
|
|
|
int
|
2000-02-18 03:38:33 +08:00
|
|
|
handle_sigsuspend (sigset_t tempmask)
|
|
|
|
{
|
2008-02-16 01:53:11 +08:00
|
|
|
sigset_t oldmask = _my_tls.sigmask; // Remember for restoration
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2012-07-22 06:58:20 +08:00
|
|
|
set_signal_mask (_my_tls.sigmask, tempmask);
|
2013-04-23 17:44:36 +08:00
|
|
|
sigproc_printf ("oldmask %ly, newmask %ly", oldmask, tempmask);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2003-01-15 03:55:42 +08:00
|
|
|
pthread_testcancel ();
|
2012-08-16 03:07:42 +08:00
|
|
|
cygwait (NULL, cw_infinite, cw_cancel | cw_cancel_self | cw_sig_eintr);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
set_sig_errno (EINTR); // Per POSIX
|
|
|
|
|
|
|
|
/* A signal dispatch function will have been added to our stack and will
|
|
|
|
be hit eventually. Set the old mask to be restored when the signal
|
2004-03-12 11:09:28 +08:00
|
|
|
handler returns and indicate its presence by modifying deltamask. */
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2004-03-12 11:09:28 +08:00
|
|
|
_my_tls.deltamask |= SIG_NONMASKABLE;
|
2003-11-29 04:55:59 +08:00
|
|
|
_my_tls.oldmask = oldmask; // Will be restored by signal handler
|
2000-02-18 03:38:33 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern DWORD exec_exit; // Possible exit value for exec
|
|
|
|
|
2001-01-17 22:57:09 +08:00
|
|
|
extern "C" {
|
|
|
|
static void
|
2013-01-31 13:26:47 +08:00
|
|
|
sig_handle_tty_stop (int sig, siginfo_t *, void *)
|
2001-01-17 22:57:09 +08:00
|
|
|
{
|
2004-09-20 12:58:36 +08:00
|
|
|
/* Silently ignore attempts to suspend if there is no accommodating
|
2001-03-02 10:09:40 +08:00
|
|
|
cygwin parent to deal with this behavior. */
|
2004-11-26 12:15:10 +08:00
|
|
|
if (!myself->cygstarted)
|
2012-07-30 11:44:40 +08:00
|
|
|
myself->process_state &= ~PID_STOPPED;
|
|
|
|
else
|
2001-06-17 01:09:19 +08:00
|
|
|
{
|
2013-04-09 09:01:19 +08:00
|
|
|
_my_tls.incyg = 1;
|
2012-07-30 11:44:40 +08:00
|
|
|
myself->stopsig = sig;
|
|
|
|
myself->alert_parent (sig);
|
|
|
|
sigproc_printf ("process %d stopped by signal %d", myself->pid, sig);
|
|
|
|
/* FIXME! This does nothing to suspend anything other than the main
|
|
|
|
thread. */
|
2013-04-09 09:01:19 +08:00
|
|
|
/* Use special cygwait parameter to handle SIGCONT. _main_tls.sig will
|
|
|
|
be cleared under lock when SIGCONT is detected. */
|
2021-01-29 11:46:26 +08:00
|
|
|
pthread::suspend_all_except_self ();
|
2013-04-09 09:01:19 +08:00
|
|
|
DWORD res = cygwait (NULL, cw_infinite, cw_sig_cont);
|
2021-01-29 11:46:26 +08:00
|
|
|
pthread::resume_all ();
|
2012-07-30 11:44:40 +08:00
|
|
|
switch (res)
|
|
|
|
{
|
|
|
|
case WAIT_SIGNALED:
|
|
|
|
myself->stopsig = SIGCONT;
|
|
|
|
myself->alert_parent (SIGCONT);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
api_fatal ("WaitSingleObject returned %d", res);
|
|
|
|
break;
|
|
|
|
}
|
2013-04-09 09:01:19 +08:00
|
|
|
_my_tls.incyg = 0;
|
2004-01-27 06:25:57 +08:00
|
|
|
}
|
2001-01-17 22:57:09 +08:00
|
|
|
}
|
2012-07-30 11:44:40 +08:00
|
|
|
} /* end extern "C" */
|
2001-01-17 22:57:09 +08:00
|
|
|
|
2004-01-14 23:45:37 +08:00
|
|
|
bool
|
2012-08-18 01:29:21 +08:00
|
|
|
_cygtls::interrupt_now (CONTEXT *cx, siginfo_t& si, void *handler,
|
2005-12-20 08:31:50 +08:00
|
|
|
struct sigaction& siga)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2005-12-20 08:31:50 +08:00
|
|
|
bool interrupted;
|
|
|
|
|
2010-08-02 03:10:52 +08:00
|
|
|
/* Delay the interrupt if we are
|
|
|
|
1) somehow inside the DLL
|
2011-07-07 02:44:06 +08:00
|
|
|
2) in _sigfe (spinning is true) and about to enter cygwin DLL
|
|
|
|
3) in a Windows DLL. */
|
|
|
|
if (incyg || spinning || inside_kernel (cx))
|
2005-12-20 08:31:50 +08:00
|
|
|
interrupted = false;
|
|
|
|
else
|
|
|
|
{
|
2022-05-17 20:12:32 +08:00
|
|
|
DWORD64 &ip = cx->_CX_instPtr;
|
2013-04-23 17:44:36 +08:00
|
|
|
push (ip);
|
2012-08-18 01:29:21 +08:00
|
|
|
interrupt_setup (si, handler, siga);
|
2013-04-23 17:44:36 +08:00
|
|
|
ip = pop ();
|
2005-12-20 08:31:50 +08:00
|
|
|
SetThreadContext (*this, cx); /* Restart the thread in a new location */
|
|
|
|
interrupted = true;
|
|
|
|
}
|
|
|
|
return interrupted;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
2005-12-20 08:31:50 +08:00
|
|
|
|
2022-05-24 03:52:52 +08:00
|
|
|
void
|
2012-08-18 01:29:21 +08:00
|
|
|
_cygtls::interrupt_setup (siginfo_t& si, void *handler, struct sigaction& siga)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2015-06-19 21:58:23 +08:00
|
|
|
push ((__tlsstack_t) sigdelayed);
|
2005-12-24 06:50:20 +08:00
|
|
|
deltamask = siga.sa_mask & ~SIG_NONMASKABLE;
|
2003-11-29 04:55:59 +08:00
|
|
|
sa_flags = siga.sa_flags;
|
2013-01-31 13:26:47 +08:00
|
|
|
func = (void (*) (int, siginfo_t *, void *)) handler;
|
2006-01-02 00:51:29 +08:00
|
|
|
if (siga.sa_flags & SA_RESETHAND)
|
|
|
|
siga.sa_handler = SIG_DFL;
|
2003-11-29 04:55:59 +08:00
|
|
|
saved_errno = -1; // Flag: no errno to save
|
2001-01-17 22:57:09 +08:00
|
|
|
if (handler == sig_handle_tty_stop)
|
|
|
|
{
|
|
|
|
myself->stopsig = 0;
|
|
|
|
myself->process_state |= PID_STOPPED;
|
|
|
|
}
|
2004-02-09 12:04:24 +08:00
|
|
|
|
2012-08-18 01:29:21 +08:00
|
|
|
infodata = si;
|
2015-06-19 22:12:10 +08:00
|
|
|
this->sig = si.si_signo; /* Should always be last thing set to avoid race */
|
2004-02-09 12:04:24 +08:00
|
|
|
|
2012-08-16 02:50:44 +08:00
|
|
|
if (incyg)
|
2015-11-27 21:39:11 +08:00
|
|
|
set_signal_arrived ();
|
2006-02-07 02:24:11 +08:00
|
|
|
|
2019-10-03 18:43:37 +08:00
|
|
|
if (!have_execed && !(myself->exec_sendsig && !ch_spawn.iscygwin ()))
|
2013-01-14 14:03:59 +08:00
|
|
|
proc_subproc (PROC_CLEARWAIT, 1);
|
2015-06-19 22:12:10 +08:00
|
|
|
sigproc_printf ("armed signal_arrived %p, signal %d",
|
|
|
|
signal_arrived, si.si_signo);
|
2000-02-28 13:05:33 +08:00
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2022-06-07 00:00:45 +08:00
|
|
|
extern "C" void
|
2000-02-18 03:38:33 +08:00
|
|
|
set_sig_errno (int e)
|
|
|
|
{
|
2003-12-18 06:47:32 +08:00
|
|
|
*_my_tls.errno_addr = e;
|
2003-11-29 04:55:59 +08:00
|
|
|
_my_tls.saved_errno = e;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2012-08-18 01:29:21 +08:00
|
|
|
int
|
|
|
|
sigpacket::setup_handler (void *handler, struct sigaction& siga, _cygtls *tls)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2000-03-10 05:04:05 +08:00
|
|
|
CONTEXT cx;
|
2002-11-22 12:43:47 +08:00
|
|
|
bool interrupted = false;
|
2000-05-17 13:49:51 +08:00
|
|
|
|
2003-11-29 04:55:59 +08:00
|
|
|
if (tls->sig)
|
2004-01-23 03:03:19 +08:00
|
|
|
{
|
2011-11-14 09:29:49 +08:00
|
|
|
sigproc_printf ("trying to send signal %d but signal %d already armed",
|
2012-08-18 01:29:21 +08:00
|
|
|
si.si_signo, tls->sig);
|
2004-01-23 03:03:19 +08:00
|
|
|
goto out;
|
|
|
|
}
|
2000-10-18 12:53:37 +08:00
|
|
|
|
2011-07-07 00:33:30 +08:00
|
|
|
for (int n = 0; n < CALL_HANDLER_RETRY_OUTER; n++)
|
2000-05-20 13:52:33 +08:00
|
|
|
{
|
2011-07-07 00:33:30 +08:00
|
|
|
for (int i = 0; i < CALL_HANDLER_RETRY_INNER; i++)
|
2002-11-22 12:43:47 +08:00
|
|
|
{
|
2011-07-07 00:33:30 +08:00
|
|
|
tls->lock ();
|
|
|
|
if (tls->incyg)
|
|
|
|
{
|
2015-06-19 22:12:10 +08:00
|
|
|
sigproc_printf ("controlled interrupt. stackptr %p, stack %p, "
|
|
|
|
"stackptr[-1] %p",
|
2011-07-07 00:33:30 +08:00
|
|
|
tls->stackptr, tls->stack, tls->stackptr[-1]);
|
2012-08-18 01:29:21 +08:00
|
|
|
tls->interrupt_setup (si, handler, siga);
|
2011-07-07 00:33:30 +08:00
|
|
|
interrupted = true;
|
|
|
|
tls->unlock ();
|
2011-07-14 01:53:21 +08:00
|
|
|
goto out;
|
2011-07-07 00:33:30 +08:00
|
|
|
}
|
2000-11-07 07:12:05 +08:00
|
|
|
|
2011-07-07 00:33:30 +08:00
|
|
|
DWORD res;
|
|
|
|
HANDLE hth = (HANDLE) *tls;
|
2012-08-17 01:11:41 +08:00
|
|
|
if (!hth)
|
2013-06-09 00:54:41 +08:00
|
|
|
{
|
|
|
|
tls->unlock ();
|
|
|
|
sigproc_printf ("thread handle NULL, not set up yet?");
|
|
|
|
}
|
2012-08-17 01:11:41 +08:00
|
|
|
else
|
2011-07-07 00:33:30 +08:00
|
|
|
{
|
2012-08-17 01:11:41 +08:00
|
|
|
/* Suspend the thread which will receive the signal.
|
|
|
|
If one of these conditions is not true we loop.
|
2015-06-19 22:12:10 +08:00
|
|
|
If the thread is already suspended (which can occur when a
|
|
|
|
program has called SuspendThread on itself) then just queue
|
|
|
|
the signal. */
|
|
|
|
sigproc_printf ("suspending thread, tls %p, _main_tls %p",
|
|
|
|
tls, _main_tls);
|
2012-08-17 01:11:41 +08:00
|
|
|
res = SuspendThread (hth);
|
|
|
|
/* Just set pending if thread is already suspended */
|
|
|
|
if (res)
|
|
|
|
{
|
2013-06-09 00:54:41 +08:00
|
|
|
tls->unlock ();
|
2012-08-17 01:11:41 +08:00
|
|
|
ResumeThread (hth);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
|
|
|
|
if (!GetThreadContext (hth, &cx))
|
|
|
|
sigproc_printf ("couldn't get context of thread, %E");
|
|
|
|
else
|
2012-08-18 01:29:21 +08:00
|
|
|
interrupted = tls->interrupt_now (&cx, si, handler, siga);
|
2012-08-17 01:11:41 +08:00
|
|
|
|
|
|
|
tls->unlock ();
|
2011-07-07 00:33:30 +08:00
|
|
|
ResumeThread (hth);
|
2012-08-17 01:11:41 +08:00
|
|
|
if (interrupted)
|
|
|
|
goto out;
|
2011-07-07 00:33:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
sigproc_printf ("couldn't interrupt. trying again.");
|
|
|
|
yield ();
|
|
|
|
}
|
|
|
|
/* Hit here if we couldn't deliver the signal. Take a more drastic
|
|
|
|
action before trying again. */
|
|
|
|
Sleep (1);
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2003-08-28 10:04:16 +08:00
|
|
|
out:
|
2015-06-19 22:12:10 +08:00
|
|
|
sigproc_printf ("signal %d %sdelivered", si.si_signo,
|
|
|
|
interrupted ? "" : "not ");
|
2000-02-24 10:49:44 +08:00
|
|
|
return interrupted;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
* wininfo.h (wininfo::timer_active): Delete.
(wininfo::itv): Ditto.
(wininfo::start_time): Ditto.
(wininfo::window_started): Ditto.
(wininfo::getitimer): Ditto.
(wininfo::setitimer): Ditto.
(wininfo::wininfo): Ditto.
(wininfo::lock): New method.
(wininfo::release): Ditto.
* window.cc: Use new lock/acquire wininfo methods throughout.
(wininfo::wininfo): Delete
(wininfo::getitimer): Ditto.
(wininfo::setitimer): Ditto.
(getitimer): Ditto.
(setitimer): Ditto.
(ualarm): Ditto.
(alarm): Ditto.
(wininfo::lock): Define new function.
(wininfo::release): Ditto.
(wininfo::process): Delete WM_TIMER handling.
* timer.cc (struct timetracker): Delete it, flags. Add it_interval,
interval_us, sleepto_us, running, init_muto(), syncthread, and gettime().
(ttstart): Make NO_COPY.
(lock_timer_tracker): New class.
(timer_tracker::timer_tracker): Distinguish ttstart case.
(timer_tracker::~timer_tracker): New destructor. Clean out events, and reset
magic.
(timer_tracker::init_muto): New method.
(to_us): Round up as per POSIX.
(timer_thread): Reorganize to match timer_tracker::settime and
timer_tracker::gettime. Call sig_send without wait. Call auto_release.
(timer_tracker::settime): Reorganize logic to avoid race. Call gettime to
recover old value.
(timer_tracker::gettime): New method.
(timer_create): Properly set errno on invalid timerid. Use new
lock_timer_tracker method.
(timer_delete): Ditto. Simplify code slightly.
(timer_gettime): New function.
(fixup_timers_after_fork): Reinit ttstart.
(getitimer): New implementation.
(setitimer): Ditto.
(ualarm): Ditto.
(alarm): Ditto.
* cygwin.din: Export timer_gettime.
* winsup.h: Remove has has_visible_window_station declaration.
* Makefile.in (DLL_OFILES): Add lsearch.o.
* cygthread.h (cygthread::notify_detached): New element.
(cygthread::cygthread): Take optional fourth argument signifying event to
signal on thread completion.
* cygthread.cc (cygthread::stub): Signal notify_detached event, if it exists.
(cygthread::cygthread): Initialize notify_detached from fourth argument.
(cygthread::detach): Wait for notify_detached field is present.
* lsearch.cc: New file.
* search.h: Ditto.
* include/cygwin/version.h: Bump API minor number to 126.
* cygwin.din: Export lsearch, lfind.
2005-03-27 09:57:38 +08:00
|
|
|
static inline bool
|
|
|
|
has_visible_window_station ()
|
|
|
|
{
|
|
|
|
HWINSTA station_hdl;
|
|
|
|
USEROBJECTFLAGS uof;
|
|
|
|
DWORD len;
|
|
|
|
|
|
|
|
/* Check if the process is associated with a visible window station.
|
|
|
|
These are processes running on the local desktop as well as processes
|
|
|
|
running in terminal server sessions.
|
|
|
|
Processes running in a service session not explicitely associated
|
|
|
|
with the desktop (using the "Allow service to interact with desktop"
|
|
|
|
property) are running in an invisible window station. */
|
|
|
|
if ((station_hdl = GetProcessWindowStation ())
|
2008-04-03 23:28:03 +08:00
|
|
|
&& GetUserObjectInformationW (station_hdl, UOI_FLAGS, &uof,
|
* wininfo.h (wininfo::timer_active): Delete.
(wininfo::itv): Ditto.
(wininfo::start_time): Ditto.
(wininfo::window_started): Ditto.
(wininfo::getitimer): Ditto.
(wininfo::setitimer): Ditto.
(wininfo::wininfo): Ditto.
(wininfo::lock): New method.
(wininfo::release): Ditto.
* window.cc: Use new lock/acquire wininfo methods throughout.
(wininfo::wininfo): Delete
(wininfo::getitimer): Ditto.
(wininfo::setitimer): Ditto.
(getitimer): Ditto.
(setitimer): Ditto.
(ualarm): Ditto.
(alarm): Ditto.
(wininfo::lock): Define new function.
(wininfo::release): Ditto.
(wininfo::process): Delete WM_TIMER handling.
* timer.cc (struct timetracker): Delete it, flags. Add it_interval,
interval_us, sleepto_us, running, init_muto(), syncthread, and gettime().
(ttstart): Make NO_COPY.
(lock_timer_tracker): New class.
(timer_tracker::timer_tracker): Distinguish ttstart case.
(timer_tracker::~timer_tracker): New destructor. Clean out events, and reset
magic.
(timer_tracker::init_muto): New method.
(to_us): Round up as per POSIX.
(timer_thread): Reorganize to match timer_tracker::settime and
timer_tracker::gettime. Call sig_send without wait. Call auto_release.
(timer_tracker::settime): Reorganize logic to avoid race. Call gettime to
recover old value.
(timer_tracker::gettime): New method.
(timer_create): Properly set errno on invalid timerid. Use new
lock_timer_tracker method.
(timer_delete): Ditto. Simplify code slightly.
(timer_gettime): New function.
(fixup_timers_after_fork): Reinit ttstart.
(getitimer): New implementation.
(setitimer): Ditto.
(ualarm): Ditto.
(alarm): Ditto.
* cygwin.din: Export timer_gettime.
* winsup.h: Remove has has_visible_window_station declaration.
* Makefile.in (DLL_OFILES): Add lsearch.o.
* cygthread.h (cygthread::notify_detached): New element.
(cygthread::cygthread): Take optional fourth argument signifying event to
signal on thread completion.
* cygthread.cc (cygthread::stub): Signal notify_detached event, if it exists.
(cygthread::cygthread): Initialize notify_detached from fourth argument.
(cygthread::detach): Wait for notify_detached field is present.
* lsearch.cc: New file.
* search.h: Ditto.
* include/cygwin/version.h: Bump API minor number to 126.
* cygwin.din: Export lsearch, lfind.
2005-03-27 09:57:38 +08:00
|
|
|
sizeof uof, &len)
|
|
|
|
&& (uof.dwFlags & WSF_VISIBLE))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-01-11 10:24:06 +08:00
|
|
|
/* Keyboard interrupt handler. */
|
2022-08-05 03:16:32 +08:00
|
|
|
static BOOL
|
2000-02-18 03:38:33 +08:00
|
|
|
ctrl_c_handler (DWORD type)
|
|
|
|
{
|
2003-07-26 12:53:59 +08:00
|
|
|
static bool saw_close;
|
2004-02-12 11:01:58 +08:00
|
|
|
|
2011-12-10 09:33:56 +08:00
|
|
|
/* Remove early or we could overthrow the threadlist in cygheap.
|
|
|
|
Deleting this line causes ash to SEGV if CTRL-C is hit repeatedly.
|
|
|
|
I am not exactly sure why that is. Maybe it's just because this
|
|
|
|
adds some early serialization to ctrl_c_handler which prevents
|
|
|
|
multiple simultaneous calls? */
|
|
|
|
_my_tls.remove (INFINITE);
|
|
|
|
|
2005-09-07 11:10:17 +08:00
|
|
|
#if 0
|
|
|
|
if (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)
|
|
|
|
proc_subproc (PROC_KILLFORKED, 0);
|
|
|
|
#endif
|
|
|
|
|
2001-07-26 08:10:52 +08:00
|
|
|
/* Return FALSE to prevent an "End task" dialog box from appearing
|
|
|
|
for each Cygwin process window that's open when the computer
|
|
|
|
is shut down or console window is closed. */
|
2003-07-26 12:53:59 +08:00
|
|
|
|
2001-07-26 08:10:52 +08:00
|
|
|
if (type == CTRL_SHUTDOWN_EVENT)
|
|
|
|
{
|
2003-06-12 20:36:07 +08:00
|
|
|
#if 0
|
|
|
|
/* Don't send a signal. Only NT service applications and their child
|
2003-07-26 12:53:59 +08:00
|
|
|
processes will receive this event and the services typically already
|
2003-06-12 20:36:07 +08:00
|
|
|
handle the shutdown action when getting the SERVICE_CONTROL_SHUTDOWN
|
|
|
|
control message. */
|
2001-07-26 08:10:52 +08:00
|
|
|
sig_send (NULL, SIGTERM);
|
2003-06-12 20:36:07 +08:00
|
|
|
#endif
|
2001-07-26 08:10:52 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
2003-07-26 12:53:59 +08:00
|
|
|
|
2023-03-05 18:02:13 +08:00
|
|
|
if (myself->ctty != CTTY_UNINITIALIZED)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2003-07-26 12:53:59 +08:00
|
|
|
if (type == CTRL_CLOSE_EVENT)
|
2004-05-29 03:50:07 +08:00
|
|
|
{
|
2003-10-14 17:21:55 +08:00
|
|
|
sig_send (NULL, SIGHUP);
|
2004-01-19 13:46:54 +08:00
|
|
|
saw_close = true;
|
2003-10-14 17:21:55 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!saw_close && type == CTRL_LOGOFF_EVENT)
|
2004-05-29 03:50:07 +08:00
|
|
|
{
|
2006-04-19 00:24:54 +08:00
|
|
|
/* The CTRL_LOGOFF_EVENT is sent when *any* user logs off.
|
|
|
|
The below code sends a SIGHUP only if it is not performing the
|
|
|
|
default activity for SIGHUP. Note that it is possible for two
|
|
|
|
SIGHUP signals to arrive if a process group leader is exiting
|
|
|
|
too. Getting this 100% right is saved for a future cygwin mailing
|
|
|
|
list goad. */
|
|
|
|
if (global_sigs[SIGHUP].sa_handler != SIG_DFL)
|
|
|
|
{
|
2013-01-03 02:34:06 +08:00
|
|
|
sig_send (myself, SIGHUP);
|
2006-04-19 00:24:54 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
2003-10-14 17:21:55 +08:00
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
2001-07-26 08:10:52 +08:00
|
|
|
|
2011-11-14 09:29:49 +08:00
|
|
|
if (ch_spawn.set_saw_ctrl_c ())
|
2022-02-26 14:13:13 +08:00
|
|
|
{
|
|
|
|
if (myself->process_state & PID_NOTCYGWIN)
|
|
|
|
sigExeced = SIGINT;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2002-01-10 11:21:27 +08:00
|
|
|
|
|
|
|
/* We're only the process group leader when we have a valid pinfo structure.
|
|
|
|
If we don't have one, then the parent "stub" will handle the signal. */
|
2002-01-21 07:13:03 +08:00
|
|
|
if (!pinfo (cygwin_pid (GetCurrentProcessId ())))
|
2002-01-10 11:21:27 +08:00
|
|
|
return TRUE;
|
|
|
|
|
2022-02-24 16:28:32 +08:00
|
|
|
if (type == CTRL_C_EVENT && ::cygheap->ctty
|
|
|
|
&& !cygheap->ctty->need_console_handler ())
|
|
|
|
/* Ctrl-C is handled in fhandler_console::cons_master_thread(). */
|
|
|
|
return TRUE;
|
|
|
|
|
2011-05-29 02:17:09 +08:00
|
|
|
tty_min *t = cygwin_shared->tty.get_cttyp ();
|
2022-02-15 22:23:50 +08:00
|
|
|
|
2022-03-01 10:34:16 +08:00
|
|
|
if (!t)
|
|
|
|
return TRUE;
|
|
|
|
|
2022-02-15 22:23:50 +08:00
|
|
|
/* If process group leader is non-cygwin process or not exist,
|
|
|
|
send signal to myself. */
|
|
|
|
pinfo pi (t->getpgid ());
|
|
|
|
if ((!pi || (pi->process_state & PID_NOTCYGWIN))
|
|
|
|
&& (!have_execed || have_execed_cygwin)
|
|
|
|
&& t->getpgid () == myself->pgid
|
|
|
|
&& type == CTRL_C_EVENT)
|
|
|
|
{
|
|
|
|
t->output_stopped = false;
|
|
|
|
sig_send(myself, SIGINT);
|
|
|
|
}
|
|
|
|
|
2015-06-19 22:12:10 +08:00
|
|
|
/* Ignore this if we're not the process group leader since it should be
|
|
|
|
handled *by* the process group leader. */
|
2012-03-29 13:45:49 +08:00
|
|
|
if (t && (!have_execed || have_execed_cygwin)
|
|
|
|
&& t->getpgid () == myself->pid &&
|
2019-03-25 05:13:00 +08:00
|
|
|
(GetTickCount64 () - t->last_ctrl_c) >= MIN_CTRL_C_SLOP)
|
2015-06-19 22:12:10 +08:00
|
|
|
/* Otherwise we just send a SIGINT to the process group and return TRUE
|
|
|
|
(to indicate that we have handled the signal). At this point, type
|
|
|
|
should be a CTRL_C_EVENT or CTRL_BREAK_EVENT. */
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2022-02-26 22:31:59 +08:00
|
|
|
int sig = SIGINT;
|
|
|
|
/* If intr and quit are both mapped to ^C, send SIGQUIT on ^BREAK */
|
|
|
|
if (type == CTRL_BREAK_EVENT
|
|
|
|
&& t->ti.c_cc[VINTR] == 3 && t->ti.c_cc[VQUIT] == 3)
|
|
|
|
sig = SIGQUIT;
|
2019-03-25 05:13:00 +08:00
|
|
|
t->last_ctrl_c = GetTickCount64 ();
|
2022-02-26 22:31:59 +08:00
|
|
|
t->kill_pgrp (sig);
|
|
|
|
t->output_stopped = false;
|
2019-03-25 05:13:00 +08:00
|
|
|
t->last_ctrl_c = GetTickCount64 ();
|
2000-02-18 03:38:33 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
2002-01-10 11:21:27 +08:00
|
|
|
|
2001-09-05 10:42:49 +08:00
|
|
|
return TRUE;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2003-11-29 04:55:59 +08:00
|
|
|
/* Function used by low level sig wrappers. */
|
2022-06-07 00:00:45 +08:00
|
|
|
extern "C" void
|
2003-11-29 04:55:59 +08:00
|
|
|
set_process_mask (sigset_t newmask)
|
|
|
|
{
|
2012-07-22 06:58:20 +08:00
|
|
|
set_signal_mask (_my_tls.sigmask, newmask);
|
2003-11-29 04:55:59 +08:00
|
|
|
}
|
|
|
|
|
2004-02-26 13:10:49 +08:00
|
|
|
extern "C" int
|
|
|
|
sighold (int sig)
|
|
|
|
{
|
|
|
|
/* check that sig is in right range */
|
2020-02-18 18:17:43 +08:00
|
|
|
if (sig < 0 || sig >= _NSIG)
|
2004-02-26 13:10:49 +08:00
|
|
|
{
|
|
|
|
set_errno (EINVAL);
|
|
|
|
syscall_printf ("signal %d out of range", sig);
|
|
|
|
return -1;
|
|
|
|
}
|
2008-02-16 01:53:11 +08:00
|
|
|
sigset_t mask = _my_tls.sigmask;
|
2004-02-26 13:10:49 +08:00
|
|
|
sigaddset (&mask, sig);
|
2012-07-22 06:58:20 +08:00
|
|
|
set_signal_mask (_my_tls.sigmask, mask);
|
2004-02-26 13:10:49 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-04-15 01:34:03 +08:00
|
|
|
extern "C" int
|
|
|
|
sigrelse (int sig)
|
|
|
|
{
|
|
|
|
/* check that sig is in right range */
|
2020-02-18 18:17:43 +08:00
|
|
|
if (sig < 0 || sig >= _NSIG)
|
2005-04-15 01:34:03 +08:00
|
|
|
{
|
|
|
|
set_errno (EINVAL);
|
|
|
|
syscall_printf ("signal %d out of range", sig);
|
|
|
|
return -1;
|
|
|
|
}
|
2008-02-16 01:53:11 +08:00
|
|
|
sigset_t mask = _my_tls.sigmask;
|
2005-04-15 01:34:03 +08:00
|
|
|
sigdelset (&mask, sig);
|
2012-07-22 06:58:20 +08:00
|
|
|
set_signal_mask (_my_tls.sigmask, mask);
|
2005-04-15 01:34:03 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-02-17 02:21:49 +08:00
|
|
|
extern "C" _sig_func_ptr
|
|
|
|
sigset (int sig, _sig_func_ptr func)
|
|
|
|
{
|
|
|
|
sig_dispatch_pending ();
|
|
|
|
_sig_func_ptr prev;
|
|
|
|
|
|
|
|
/* check that sig is in right range */
|
2020-02-18 18:17:43 +08:00
|
|
|
if (sig < 0 || sig >= _NSIG || sig == SIGKILL || sig == SIGSTOP)
|
2006-02-17 02:21:49 +08:00
|
|
|
{
|
|
|
|
set_errno (EINVAL);
|
|
|
|
syscall_printf ("SIG_ERR = sigset (%d, %p)", sig, func);
|
|
|
|
return (_sig_func_ptr) SIG_ERR;
|
|
|
|
}
|
|
|
|
|
2008-02-16 01:53:11 +08:00
|
|
|
sigset_t mask = _my_tls.sigmask;
|
2006-02-17 02:21:49 +08:00
|
|
|
/* If sig was in the signal mask return SIG_HOLD, otherwise return the
|
|
|
|
previous disposition. */
|
|
|
|
if (sigismember (&mask, sig))
|
|
|
|
prev = SIG_HOLD;
|
|
|
|
else
|
|
|
|
prev = global_sigs[sig].sa_handler;
|
|
|
|
/* If func is SIG_HOLD, add sig to the signal mask, otherwise set the
|
|
|
|
disposition to func and remove sig from the signal mask. */
|
|
|
|
if (func == SIG_HOLD)
|
|
|
|
sigaddset (&mask, sig);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* No error checking. The test which could return SIG_ERR has already
|
2006-05-28 23:50:14 +08:00
|
|
|
been made above. */
|
2006-02-17 02:21:49 +08:00
|
|
|
signal (sig, func);
|
|
|
|
sigdelset (&mask, sig);
|
|
|
|
}
|
2012-07-22 06:58:20 +08:00
|
|
|
set_signal_mask (_my_tls.sigmask, mask);
|
2006-02-17 02:21:49 +08:00
|
|
|
return prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int
|
|
|
|
sigignore (int sig)
|
|
|
|
{
|
|
|
|
return sigset (sig, SIG_IGN) == SIG_ERR ? -1 : 0;
|
|
|
|
}
|
|
|
|
|
2005-12-24 06:50:20 +08:00
|
|
|
/* Update the signal mask for this process and return the old mask.
|
2012-08-03 23:38:59 +08:00
|
|
|
Called from call_signal_handler */
|
2004-03-12 11:09:28 +08:00
|
|
|
extern "C" sigset_t
|
|
|
|
set_process_mask_delta ()
|
|
|
|
{
|
|
|
|
sigset_t newmask, oldmask;
|
|
|
|
|
|
|
|
if (_my_tls.deltamask & SIG_NONMASKABLE)
|
|
|
|
oldmask = _my_tls.oldmask; /* from handle_sigsuspend */
|
|
|
|
else
|
2008-02-16 01:53:11 +08:00
|
|
|
oldmask = _my_tls.sigmask;
|
2004-03-12 11:09:28 +08:00
|
|
|
newmask = (oldmask | _my_tls.deltamask) & ~SIG_NONMASKABLE;
|
2013-04-23 17:44:36 +08:00
|
|
|
sigproc_printf ("oldmask %lx, newmask %lx, deltamask %lx", oldmask, newmask,
|
2004-03-12 11:09:28 +08:00
|
|
|
_my_tls.deltamask);
|
2008-02-16 01:53:11 +08:00
|
|
|
_my_tls.sigmask = newmask;
|
2004-03-12 11:09:28 +08:00
|
|
|
return oldmask;
|
|
|
|
}
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
/* Set the signal mask for this process.
|
2000-11-16 13:16:59 +08:00
|
|
|
Note that some signals are unmaskable, as in UNIX. */
|
2012-07-22 06:58:20 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
set_signal_mask (sigset_t& setmask, sigset_t newmask)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
newmask &= ~SIG_NONMASKABLE;
|
2012-07-22 06:58:20 +08:00
|
|
|
sigset_t mask_bits = setmask & ~newmask;
|
2013-04-23 17:44:36 +08:00
|
|
|
sigproc_printf ("setmask %lx, newmask %lx, mask_bits %lx", setmask, newmask,
|
2003-12-24 00:26:31 +08:00
|
|
|
mask_bits);
|
2012-07-22 06:58:20 +08:00
|
|
|
setmask = newmask;
|
2003-12-24 00:26:31 +08:00
|
|
|
if (mask_bits)
|
2004-02-02 02:29:12 +08:00
|
|
|
sig_dispatch_pending (true);
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2015-07-05 04:49:30 +08:00
|
|
|
|
2022-08-05 03:16:32 +08:00
|
|
|
DWORD
|
2015-07-05 04:49:30 +08:00
|
|
|
dumpstack_overflow_wrapper (PVOID arg)
|
|
|
|
{
|
|
|
|
cygwin_exception *exc = (cygwin_exception *) arg;
|
2016-07-28 07:40:23 +08:00
|
|
|
SetThreadName (GetCurrentThreadId (), "__dumpstack_overflow");
|
2015-07-05 04:49:30 +08:00
|
|
|
exc->dumpstack ();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-03 02:34:06 +08:00
|
|
|
/* Exit due to a signal. Should only be called from the signal thread. */
|
|
|
|
extern "C" {
|
|
|
|
static void
|
2015-07-05 04:49:30 +08:00
|
|
|
signal_exit (int sig, siginfo_t *si, void *)
|
2013-01-03 02:34:06 +08:00
|
|
|
{
|
|
|
|
debug_printf ("exiting due to signal %d", sig);
|
|
|
|
exit_state = ES_SIGNAL_EXIT;
|
|
|
|
|
|
|
|
switch (sig)
|
|
|
|
{
|
|
|
|
case SIGABRT:
|
|
|
|
case SIGBUS:
|
|
|
|
case SIGFPE:
|
|
|
|
case SIGILL:
|
|
|
|
case SIGQUIT:
|
|
|
|
case SIGSEGV:
|
|
|
|
case SIGSYS:
|
|
|
|
case SIGTRAP:
|
|
|
|
case SIGXCPU:
|
|
|
|
case SIGXFSZ:
|
2013-05-01 07:47:01 +08:00
|
|
|
if (try_to_debug ())
|
|
|
|
break;
|
2024-01-12 04:00:14 +08:00
|
|
|
|
|
|
|
if (cygheap->rlim_core == 0Ul)
|
|
|
|
break;
|
|
|
|
|
2024-01-11 04:35:49 +08:00
|
|
|
sig |= __WCOREFLAG; /* Set flag in exit status to show that we've "dumped core" */
|
2024-01-12 04:00:14 +08:00
|
|
|
|
|
|
|
/* If core dump size is >1MB, try to invoke dumper to write a
|
|
|
|
.core file */
|
|
|
|
if (cygheap->rlim_core > 1024*1024)
|
|
|
|
{
|
|
|
|
if (exec_prepared_command (dumper_command))
|
|
|
|
break;
|
|
|
|
/* If that failed, fall-through to... */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Otherwise write a .stackdump */
|
2013-05-01 07:47:01 +08:00
|
|
|
if (si->si_code != SI_USER && si->si_cyg)
|
2015-07-05 04:49:30 +08:00
|
|
|
{
|
|
|
|
cygwin_exception *exc = (cygwin_exception *) si->si_cyg;
|
|
|
|
if ((NTSTATUS) exc->exception_record ()->ExceptionCode
|
|
|
|
== STATUS_STACK_OVERFLOW)
|
|
|
|
{
|
|
|
|
/* We're handling a stack overflow so we're running low
|
|
|
|
on stack (surprise!) The dumpstack method needs lots
|
|
|
|
of stack for buffers. So what we do here is to run
|
|
|
|
dumpstack in another thread with its own stack. */
|
|
|
|
HANDLE thread = CreateThread (&sec_none_nih, 0,
|
|
|
|
dumpstack_overflow_wrapper,
|
|
|
|
exc, 0, NULL);
|
|
|
|
if (thread)
|
|
|
|
{
|
|
|
|
WaitForSingleObject (thread, INFINITE);
|
|
|
|
CloseHandle (thread);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
((cygwin_exception *) si->si_cyg)->dumpstack ();
|
|
|
|
}
|
2013-05-01 07:47:01 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
CONTEXT c;
|
|
|
|
c.ContextFlags = CONTEXT_FULL;
|
2013-07-20 07:04:32 +08:00
|
|
|
RtlCaptureContext (&c);
|
2013-07-21 01:11:44 +08:00
|
|
|
cygwin_exception exc ((PUINT_PTR) __builtin_frame_address (0), &c);
|
2013-05-01 07:47:01 +08:00
|
|
|
exc.dumpstack ();
|
|
|
|
}
|
|
|
|
break;
|
2013-01-03 02:34:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
lock_process until_exit (true);
|
|
|
|
|
|
|
|
if (have_execed || exit_state > ES_PROCESS_LOCKED)
|
2013-05-01 07:47:01 +08:00
|
|
|
{
|
|
|
|
debug_printf ("recursive exit?");
|
|
|
|
myself.exit (sig);
|
|
|
|
}
|
2013-01-03 02:34:06 +08:00
|
|
|
|
|
|
|
/* Starve other threads in a vain attempt to stop them from doing something
|
|
|
|
stupid. */
|
|
|
|
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
|
|
|
|
|
|
|
|
sigproc_printf ("about to call do_exit (%x)", sig);
|
|
|
|
do_exit (sig);
|
|
|
|
}
|
|
|
|
} /* extern "C" */
|
|
|
|
|
2024-01-12 05:34:27 +08:00
|
|
|
/* As above, but before exiting due to api_fatal */
|
|
|
|
extern "C"
|
|
|
|
void
|
|
|
|
api_fatal_debug ()
|
|
|
|
{
|
|
|
|
if (try_to_debug ())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (cygheap->rlim_core == 0Ul)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (cygheap->rlim_core > 1024*1024)
|
|
|
|
if (exec_prepared_command (dumper_command))
|
|
|
|
return;
|
|
|
|
|
|
|
|
cygwin_stackdump();
|
|
|
|
}
|
|
|
|
|
2013-04-09 09:01:19 +08:00
|
|
|
/* Attempt to carefully handle SIGCONT when we are stopped. */
|
|
|
|
void
|
|
|
|
_cygtls::handle_SIGCONT ()
|
|
|
|
{
|
2013-06-08 22:38:20 +08:00
|
|
|
if (NOTSTATE (myself, PID_STOPPED))
|
|
|
|
return;
|
|
|
|
|
|
|
|
myself->stopsig = 0;
|
|
|
|
myself->process_state &= ~PID_STOPPED;
|
|
|
|
/* Carefully tell sig_handle_tty_stop to wake up.
|
|
|
|
Make sure that any pending signal is handled before trying to
|
|
|
|
send a new one. Then make sure that SIGCONT has been recognized
|
|
|
|
before exiting the loop. */
|
|
|
|
bool sigsent = false;
|
|
|
|
while (1)
|
|
|
|
if (sig) /* Assume that it's ok to just test sig outside of a
|
|
|
|
lock since setup_handler does it this way. */
|
|
|
|
yield (); /* Attempt to schedule another thread. */
|
|
|
|
else if (sigsent)
|
|
|
|
break; /* SIGCONT has been recognized by other thread */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sig = SIGCONT;
|
2015-11-27 21:39:11 +08:00
|
|
|
set_signal_arrived (); /* alert sig_handle_tty_stop */
|
2013-06-08 22:38:20 +08:00
|
|
|
sigsent = true;
|
|
|
|
}
|
2013-04-09 09:01:19 +08:00
|
|
|
/* Clear pending stop signals */
|
|
|
|
sig_clear (SIGSTOP);
|
|
|
|
sig_clear (SIGTSTP);
|
|
|
|
sig_clear (SIGTTIN);
|
|
|
|
sig_clear (SIGTTOU);
|
|
|
|
}
|
|
|
|
|
2022-05-24 03:52:52 +08:00
|
|
|
int
|
2004-01-19 13:46:54 +08:00
|
|
|
sigpacket::process ()
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2013-03-31 20:35:44 +08:00
|
|
|
int rc = 1;
|
|
|
|
bool issig_wait = false;
|
|
|
|
struct sigaction& thissig = global_sigs[si.si_signo];
|
|
|
|
void *handler = have_execed ? NULL : (void *) thissig.sa_handler;
|
2006-07-18 03:30:30 +08:00
|
|
|
|
2014-11-29 04:46:13 +08:00
|
|
|
threadlist_t *tl_entry = NULL;
|
|
|
|
_cygtls *tls = NULL;
|
|
|
|
|
2013-04-09 09:01:19 +08:00
|
|
|
/* Don't try to send signals if we're just starting up since signal masks
|
|
|
|
may not be available. */
|
2013-03-31 20:35:44 +08:00
|
|
|
if (!cygwin_finished_initializing)
|
|
|
|
{
|
|
|
|
rc = -1;
|
2013-04-09 09:01:19 +08:00
|
|
|
goto done;
|
* devices.cc: New file.
* devices.gperf: New file.
* devices.shilka: New file.
* cygwin-gperf: New file.
* cygwin-shilka: New file.
* fhandler_fifo.cc: New file.
* fhandler_nodevice.cc : New file. Reorganize headers so that path.h precedes
fhandler.h throughout. Remove device argument and unit arguments from fhandler
constructors throughout. Remove pc arguments to fhandler functions and use
internal pc element instead, throughout. Use dev element in pc throughout.
Use major/minor elements rather than units and device numbers previously in
fhandler class. Use correct methods for fhandler file names rather than
directly accessing file name variables, throughout.
* Makefile.in (DLL_OFILES): Add devices.o, fhandler_fifo.o
* dcrt0.cc (dll_crt0_1): Call device::init.
* devices.h: Renumber devices based on more Linux-like major/minor numbers.
Add more devices. Declare standard device storage.
(device): Declare struct.
* dir.cc (opendir): Use new 'build_fh_name' to construct a fhandler_* type.
* dtable.cc (dtable::get_debugger_info): Ditto.
(cygwin_attach_handle_to_fd): Ditto.
(dtable::release): Remove special FH_SOCKET case in favor of generic
"need_fixup_before" test.
(dtable::init_std_file_from_handle): Use either build_fh_dev or build_fh_name
to build standard fhandler.
(dtable::build_fh_name): Renamed from dtable::build_fhandler_from_name. Move
out of dtable class. Don't accept a path_conv argument. Just build it here
and pass it to:
(build_fh_pc): Renamed from dtable::build_fhandler. Move out of dtable class.
Use intrinsic device type in path_conv to create new fhandler.
(build_fh_dev): Renamed from dtable::build_fhandler. Move out of dtable class.
Simplify arguments to just take new 'device' type and a name. Just return
pointer to fhandler rather than trying to insert into dtable.
(dtable::dup_worker): Accommodate above build_fh name changes.
(dtable::find_fifo): New (currently broken) function.
(handle_to_fn): Use strechr for efficiency.
* dtable.h: Reflect above build_fh name changes and argument differences.
(fhandler_base *&operator []): Return self rather than copy of self.
* fhandler.cc (fhandler_base::operator =): Use pc element to set normalized
path.
(fhandler_base::set_name): Ditto.
(fhandler_base::raw_read): Use method to access name.
(fhandler_base::write): Correctly use get_output_handle rather than get_handle.
(handler_base::device_access_denied): New function.
(fhandler_base::open): Eliminate pc argument and use pc element of
fhandler_base throughout.
(fhandler_base::fstat): Detect if device is based in filesystem and use
fstat_fs to calculate stat, if so.
(fhandler_base::fhandler_base): Eliminate handling of file names and, instead,
just free appropriate component from pc.
(fhandler_base::opendir): Remove path_conv parameter.
* fhandler.h: Remove all device flags.
(fhandler_base::pc): New element.
(fhandler_base::set_name): Change argument to path_conv.
(fhandler_base::error): New function.
(fhandler_base::exists): New function.
(fhandler_base::pc_binmode): New function.
(fhandler_base::dev): New function.
(fhandler_base::open_fs): New function.
(fhandler_base::fstat_fs): New function.
(fhandler_base::fstat_by_name): New function.
(fhandler_base::fstat_by_handle): New function.
(fhandler_base::isfifo): New function.
(fhandler_base::is_slow): New function.
(fhandler_base::is_auto_device): New function.
(fhandler_base::is_fs_special): New function.
(fhandler_base::device_access_denied): New function.
(fhandler_base::operator DWORD&): New operator.
(fhandler_base::get_name): Return normalized path from pc.
(fhandler_base::get_win32_name): Return windows path from pc.
(fhandler_base::isdevice): Renamed from is_device.
(fhandler_base::get_native_name): Return device format.
(fhandler_fifo): New class.
(fhandler_nodevice): New class.
(select_stuff::device_specific): Remove array.
(select_stuff::device_specific_pipe): New class element.
(select_stuff::device_specific_socket): New class element.
(select_stuff::device_specific_serial): New class element.
(select_stuff::select_stuff): Initialize new elements.
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Move to base class
from fhandler_disk_file.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_disk_file::open): Move most functionality into
fhandler_base::open_fs.
(fhandler_base::open_fs): New function.
(fhandler_disk_file::close): Move most functionality into
fhandler_base::close_fs.
(fhandler_base::close_fs): New function.
* fhandler_mem.cc (fhandler_dev_mem::open): Use device name in debugging
output.
* fhandler_socket.cc (fhandler_socket::set_connect_secret): Copy standard
urandom device into appropriate place.
(fhandler_socket::accept): Reflect change in fdsock return value.
* fhandler_tty.cc: See "throughouts" above.
* net.cc: Accommodate fdsock change throughout.
(fdsock): Return success or failure, accept fd argument and device argument.
* path.cc (symlink_info::major): New element.
(symlink_info::minor): New element.
(symlink_info::parse_device): Declare new function.
(fs_info::update): Accommodate changes in path_conv class.
(path_conv::fillin): Ditto.
(path_conv::return_and_clear_normalized_path): Eliminate.
(path_conv::set_normalized_path): New function.
(path_conv::path_conv): Set info in dev element. Use path_conv methods Check
for FH_FS rather than FH_BAD to indicate when to fill in filesystem stuff.
where appropriate rather than direct access. Use set_normalized_path to set
normalized path.
(windows_device_names): Eliminate.
(get_dev): Ditto.
(get_raw_device_number): Ditto.
(get_device_number): Ditto.
(win32_device_name): Call new device name parser to do most of the heavy
lifting.
(mount_info::conv_to_win32_path): Fill in dev field as appropriate.
(symlink_worker): Handle new device files.
(symlink_info::check): Ditto.
(symlink_info::parse_device): Define new function.
* path.h (executable_states): Move here from fhandler.h.
(fs_info): Rename variables to *_storage and create methods for accessing same.
(path_conv): Add dev element, remove devn and unit and adjust inline methods to
accommodate.
(set_normalized_path): Declare new function.
* pinfo.cc (_pinfo::commune_recv): Add broken support for handling fifos.
(_pinfo::commune_send): Ditto.
* pipe.cc (fhandler_pipe::close): check for existence of handle before closing
it.
(handler_pipe::create): Rename from make_pipe. Change arguments to accept
fhandler_pipe array. Accommodate fifos.
(pipe): Rework to deal with fhandler_pipe::create changes.
(_pipe): Ditto.
* select.cc: Use individual device_specific types throughout rather than
indexing with obsolete device number.
(set_bits): Use is_socket call rather than checking device number.
* shared_info.h (CURR_MOUNT_MAGIC): Update.
(conv_to_win32_path): Reflect addition of device argument.
* syscalls.cc (mknod_worker): New function.
(open): Use build_fh_name to build fhandler.
(chown_worker): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(chmod_device): New function.
(chmod): Detect if this is an 'auto' device rather than an on-filesystem device
and handle appropriately. Use chmod_device to set mode of in-filesystem
devices.
(stat_worker): Eliminate path_conv argument. Call build_fh_name to construct
fhandler. Use fh->error() rather than pc->error to detect errors in fhandler
construction.
(access_worker): New function pulled from access. Accommodate in-filesystem
devices.
(access): Use access_worker.
(fpathconf): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(mknod_worker): New function.
(mknod32): New function.
(chroot): Free normalized path -- assuming it was actually cmalloced.
* tty.cc (create_tty_master): Tweak for new device class.
(tty::common_init): Ditto.
* winsup.h (stat_worker): Remove.
(symlink_worker): Declare.
* exceptions.cc (set_process_mask): Just call sig_dispatch_pending and don't
worry about pending_signals since sig_dispatch_pending should always do the
right thing now.
(sig_handle): Reorganize SIGCONT handling to more closely conform to SUSv3.
* pinfo.h: Move __SIG enum to sigproc.h.
(PICOM_FIFO): New enum element.
(_pinfo): Remove 'thread2signal' stuff throughout class.
(_pinfo::commune_send): Make varargs.
(_pinfo::sigtodo): Eliminate.
(_pinfo::thread2signal): Ditto.
* signal.cc (kill_worker): Eliminate call to setthread2signal.
* sigproc.cc (local_sigtodo): Eliminate.
(getlocal_sigtodo): Ditto.
(sigelem): New class.
(pending_signals): New class.
(sigqueue): New variable, start of sigqueue linked list.
(sigcatch_nonmain): Eliminate.
(sigcatch_main): Eliminate.
(sigcatch_nosync): Eliminate.
(sigcomplete_nonmain): Eliminate.
(pending_signals): Eliminate.
(sig_clear): Call signal thread to clear pending signals, unless already in
signal thread.
(sigpending): Call signal thread to get pending signals.
(sig_dispatch_pending): Eliminate use of pending_signals and just check
sigqueue.
(sigproc_terminate): Eliminate all of the obsolete semaphore stuff. Close
signal pipe handle.
(sig_send): Eliminate all of the obsolete semaphore stuff and use pipe to send
signals.
(getevent): Eliminate.
(pending_signals::add): New function.
(pending_signals::del): New function.
(pending_signals::next): New function.
(wait_sig): Eliminate all of the obsolete semaphore stuff. Use pipe to
communicate and maintain a linked list of signals.
* sigproc.h: Move __SIG defines here. Add __SIGPENDING.
(sig_dispatch_pending): Remove "C" specifier.
(sig_handle): Accept a mask argument.
* thread.cc: Remove signal handling considerations throughout.
2003-09-25 08:37:18 +08:00
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2004-01-19 13:46:54 +08:00
|
|
|
sigproc_printf ("signal %d processing", si.si_signo);
|
|
|
|
|
|
|
|
myself->rusage_self.ru_nsignals++;
|
|
|
|
|
2013-04-09 09:01:19 +08:00
|
|
|
if (si.si_signo == SIGCONT)
|
2014-11-29 04:46:13 +08:00
|
|
|
{
|
|
|
|
tl_entry = cygheap->find_tls (_main_tls);
|
|
|
|
_main_tls->handle_SIGCONT ();
|
|
|
|
cygheap->unlock_tls (tl_entry);
|
|
|
|
}
|
2013-04-09 09:01:19 +08:00
|
|
|
|
2014-11-29 04:46:13 +08:00
|
|
|
/* SIGKILL is special. It always goes through. */
|
2013-04-09 09:01:19 +08:00
|
|
|
if (si.si_signo == SIGKILL)
|
2014-11-29 04:46:13 +08:00
|
|
|
{
|
|
|
|
tl_entry = cygheap->find_tls (_main_tls);
|
|
|
|
tls = _main_tls;
|
|
|
|
}
|
2013-04-09 09:01:19 +08:00
|
|
|
else if (ISSTATE (myself, PID_STOPPED))
|
|
|
|
{
|
|
|
|
rc = -1; /* Don't send signals when stopped */
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
else if (!sigtls)
|
2012-12-08 01:37:33 +08:00
|
|
|
{
|
2014-11-29 04:46:13 +08:00
|
|
|
tl_entry = cygheap->find_tls (si.si_signo, issig_wait);
|
|
|
|
if (tl_entry)
|
|
|
|
{
|
|
|
|
tls = tl_entry->thread;
|
|
|
|
sigproc_printf ("using tls %p", tls);
|
|
|
|
}
|
2012-12-08 01:37:33 +08:00
|
|
|
}
|
2012-07-22 06:58:20 +08:00
|
|
|
else
|
|
|
|
{
|
2014-11-29 04:46:13 +08:00
|
|
|
tl_entry = cygheap->find_tls (sigtls);
|
|
|
|
if (tl_entry)
|
|
|
|
{
|
|
|
|
tls = tl_entry->thread;
|
|
|
|
if (sigismember (&tls->sigwait_mask, si.si_signo))
|
|
|
|
issig_wait = true;
|
|
|
|
else if (!sigismember (&tls->sigmask, si.si_signo))
|
|
|
|
issig_wait = false;
|
|
|
|
else
|
2015-10-31 00:21:30 +08:00
|
|
|
tls = NULL;
|
2014-11-29 04:46:13 +08:00
|
|
|
}
|
2013-03-31 20:35:44 +08:00
|
|
|
}
|
2020-03-11 20:28:27 +08:00
|
|
|
|
2013-04-09 09:01:19 +08:00
|
|
|
/* !tls means no threads available to catch a signal. */
|
|
|
|
if (!tls)
|
2013-03-31 20:35:44 +08:00
|
|
|
{
|
|
|
|
sigproc_printf ("signal %d blocked", si.si_signo);
|
|
|
|
rc = -1;
|
|
|
|
goto done;
|
2012-07-22 06:58:20 +08:00
|
|
|
}
|
2008-11-28 10:56:09 +08:00
|
|
|
|
2013-03-10 05:55:18 +08:00
|
|
|
/* Do stuff for gdb */
|
|
|
|
if ((HANDLE) *tls)
|
|
|
|
tls->signal_debugger (si);
|
|
|
|
|
2013-03-31 20:35:44 +08:00
|
|
|
if (issig_wait)
|
|
|
|
{
|
|
|
|
tls->sigwait_mask = 0;
|
|
|
|
goto dosig;
|
|
|
|
}
|
2012-12-08 04:59:44 +08:00
|
|
|
|
|
|
|
if (handler == SIG_IGN)
|
|
|
|
{
|
2019-01-13 04:19:52 +08:00
|
|
|
if (si.si_code == SI_TIMER)
|
2019-01-22 22:23:05 +08:00
|
|
|
((timer_tracker *) si.si_tid)->disarm_overrun_event ();
|
2012-12-08 04:59:44 +08:00
|
|
|
sigproc_printf ("signal %d ignored", si.si_signo);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2004-01-19 13:46:54 +08:00
|
|
|
if (si.si_signo == SIGKILL)
|
|
|
|
goto exit_sig;
|
2005-08-25 11:12:48 +08:00
|
|
|
if (si.si_signo == SIGSTOP)
|
* devices.cc: New file.
* devices.gperf: New file.
* devices.shilka: New file.
* cygwin-gperf: New file.
* cygwin-shilka: New file.
* fhandler_fifo.cc: New file.
* fhandler_nodevice.cc : New file. Reorganize headers so that path.h precedes
fhandler.h throughout. Remove device argument and unit arguments from fhandler
constructors throughout. Remove pc arguments to fhandler functions and use
internal pc element instead, throughout. Use dev element in pc throughout.
Use major/minor elements rather than units and device numbers previously in
fhandler class. Use correct methods for fhandler file names rather than
directly accessing file name variables, throughout.
* Makefile.in (DLL_OFILES): Add devices.o, fhandler_fifo.o
* dcrt0.cc (dll_crt0_1): Call device::init.
* devices.h: Renumber devices based on more Linux-like major/minor numbers.
Add more devices. Declare standard device storage.
(device): Declare struct.
* dir.cc (opendir): Use new 'build_fh_name' to construct a fhandler_* type.
* dtable.cc (dtable::get_debugger_info): Ditto.
(cygwin_attach_handle_to_fd): Ditto.
(dtable::release): Remove special FH_SOCKET case in favor of generic
"need_fixup_before" test.
(dtable::init_std_file_from_handle): Use either build_fh_dev or build_fh_name
to build standard fhandler.
(dtable::build_fh_name): Renamed from dtable::build_fhandler_from_name. Move
out of dtable class. Don't accept a path_conv argument. Just build it here
and pass it to:
(build_fh_pc): Renamed from dtable::build_fhandler. Move out of dtable class.
Use intrinsic device type in path_conv to create new fhandler.
(build_fh_dev): Renamed from dtable::build_fhandler. Move out of dtable class.
Simplify arguments to just take new 'device' type and a name. Just return
pointer to fhandler rather than trying to insert into dtable.
(dtable::dup_worker): Accommodate above build_fh name changes.
(dtable::find_fifo): New (currently broken) function.
(handle_to_fn): Use strechr for efficiency.
* dtable.h: Reflect above build_fh name changes and argument differences.
(fhandler_base *&operator []): Return self rather than copy of self.
* fhandler.cc (fhandler_base::operator =): Use pc element to set normalized
path.
(fhandler_base::set_name): Ditto.
(fhandler_base::raw_read): Use method to access name.
(fhandler_base::write): Correctly use get_output_handle rather than get_handle.
(handler_base::device_access_denied): New function.
(fhandler_base::open): Eliminate pc argument and use pc element of
fhandler_base throughout.
(fhandler_base::fstat): Detect if device is based in filesystem and use
fstat_fs to calculate stat, if so.
(fhandler_base::fhandler_base): Eliminate handling of file names and, instead,
just free appropriate component from pc.
(fhandler_base::opendir): Remove path_conv parameter.
* fhandler.h: Remove all device flags.
(fhandler_base::pc): New element.
(fhandler_base::set_name): Change argument to path_conv.
(fhandler_base::error): New function.
(fhandler_base::exists): New function.
(fhandler_base::pc_binmode): New function.
(fhandler_base::dev): New function.
(fhandler_base::open_fs): New function.
(fhandler_base::fstat_fs): New function.
(fhandler_base::fstat_by_name): New function.
(fhandler_base::fstat_by_handle): New function.
(fhandler_base::isfifo): New function.
(fhandler_base::is_slow): New function.
(fhandler_base::is_auto_device): New function.
(fhandler_base::is_fs_special): New function.
(fhandler_base::device_access_denied): New function.
(fhandler_base::operator DWORD&): New operator.
(fhandler_base::get_name): Return normalized path from pc.
(fhandler_base::get_win32_name): Return windows path from pc.
(fhandler_base::isdevice): Renamed from is_device.
(fhandler_base::get_native_name): Return device format.
(fhandler_fifo): New class.
(fhandler_nodevice): New class.
(select_stuff::device_specific): Remove array.
(select_stuff::device_specific_pipe): New class element.
(select_stuff::device_specific_socket): New class element.
(select_stuff::device_specific_serial): New class element.
(select_stuff::select_stuff): Initialize new elements.
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Move to base class
from fhandler_disk_file.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_disk_file::open): Move most functionality into
fhandler_base::open_fs.
(fhandler_base::open_fs): New function.
(fhandler_disk_file::close): Move most functionality into
fhandler_base::close_fs.
(fhandler_base::close_fs): New function.
* fhandler_mem.cc (fhandler_dev_mem::open): Use device name in debugging
output.
* fhandler_socket.cc (fhandler_socket::set_connect_secret): Copy standard
urandom device into appropriate place.
(fhandler_socket::accept): Reflect change in fdsock return value.
* fhandler_tty.cc: See "throughouts" above.
* net.cc: Accommodate fdsock change throughout.
(fdsock): Return success or failure, accept fd argument and device argument.
* path.cc (symlink_info::major): New element.
(symlink_info::minor): New element.
(symlink_info::parse_device): Declare new function.
(fs_info::update): Accommodate changes in path_conv class.
(path_conv::fillin): Ditto.
(path_conv::return_and_clear_normalized_path): Eliminate.
(path_conv::set_normalized_path): New function.
(path_conv::path_conv): Set info in dev element. Use path_conv methods Check
for FH_FS rather than FH_BAD to indicate when to fill in filesystem stuff.
where appropriate rather than direct access. Use set_normalized_path to set
normalized path.
(windows_device_names): Eliminate.
(get_dev): Ditto.
(get_raw_device_number): Ditto.
(get_device_number): Ditto.
(win32_device_name): Call new device name parser to do most of the heavy
lifting.
(mount_info::conv_to_win32_path): Fill in dev field as appropriate.
(symlink_worker): Handle new device files.
(symlink_info::check): Ditto.
(symlink_info::parse_device): Define new function.
* path.h (executable_states): Move here from fhandler.h.
(fs_info): Rename variables to *_storage and create methods for accessing same.
(path_conv): Add dev element, remove devn and unit and adjust inline methods to
accommodate.
(set_normalized_path): Declare new function.
* pinfo.cc (_pinfo::commune_recv): Add broken support for handling fifos.
(_pinfo::commune_send): Ditto.
* pipe.cc (fhandler_pipe::close): check for existence of handle before closing
it.
(handler_pipe::create): Rename from make_pipe. Change arguments to accept
fhandler_pipe array. Accommodate fifos.
(pipe): Rework to deal with fhandler_pipe::create changes.
(_pipe): Ditto.
* select.cc: Use individual device_specific types throughout rather than
indexing with obsolete device number.
(set_bits): Use is_socket call rather than checking device number.
* shared_info.h (CURR_MOUNT_MAGIC): Update.
(conv_to_win32_path): Reflect addition of device argument.
* syscalls.cc (mknod_worker): New function.
(open): Use build_fh_name to build fhandler.
(chown_worker): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(chmod_device): New function.
(chmod): Detect if this is an 'auto' device rather than an on-filesystem device
and handle appropriately. Use chmod_device to set mode of in-filesystem
devices.
(stat_worker): Eliminate path_conv argument. Call build_fh_name to construct
fhandler. Use fh->error() rather than pc->error to detect errors in fhandler
construction.
(access_worker): New function pulled from access. Accommodate in-filesystem
devices.
(access): Use access_worker.
(fpathconf): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(mknod_worker): New function.
(mknod32): New function.
(chroot): Free normalized path -- assuming it was actually cmalloced.
* tty.cc (create_tty_master): Tweak for new device class.
(tty::common_init): Ditto.
* winsup.h (stat_worker): Remove.
(symlink_worker): Declare.
* exceptions.cc (set_process_mask): Just call sig_dispatch_pending and don't
worry about pending_signals since sig_dispatch_pending should always do the
right thing now.
(sig_handle): Reorganize SIGCONT handling to more closely conform to SUSv3.
* pinfo.h: Move __SIG enum to sigproc.h.
(PICOM_FIFO): New enum element.
(_pinfo): Remove 'thread2signal' stuff throughout class.
(_pinfo::commune_send): Make varargs.
(_pinfo::sigtodo): Eliminate.
(_pinfo::thread2signal): Ditto.
* signal.cc (kill_worker): Eliminate call to setthread2signal.
* sigproc.cc (local_sigtodo): Eliminate.
(getlocal_sigtodo): Ditto.
(sigelem): New class.
(pending_signals): New class.
(sigqueue): New variable, start of sigqueue linked list.
(sigcatch_nonmain): Eliminate.
(sigcatch_main): Eliminate.
(sigcatch_nosync): Eliminate.
(sigcomplete_nonmain): Eliminate.
(pending_signals): Eliminate.
(sig_clear): Call signal thread to clear pending signals, unless already in
signal thread.
(sigpending): Call signal thread to get pending signals.
(sig_dispatch_pending): Eliminate use of pending_signals and just check
sigqueue.
(sigproc_terminate): Eliminate all of the obsolete semaphore stuff. Close
signal pipe handle.
(sig_send): Eliminate all of the obsolete semaphore stuff and use pipe to send
signals.
(getevent): Eliminate.
(pending_signals::add): New function.
(pending_signals::del): New function.
(pending_signals::next): New function.
(wait_sig): Eliminate all of the obsolete semaphore stuff. Use pipe to
communicate and maintain a linked list of signals.
* sigproc.h: Move __SIG defines here. Add __SIGPENDING.
(sig_dispatch_pending): Remove "C" specifier.
(sig_handle): Accept a mask argument.
* thread.cc: Remove signal handling considerations throughout.
2003-09-25 08:37:18 +08:00
|
|
|
{
|
2004-01-19 13:46:54 +08:00
|
|
|
sig_clear (SIGCONT);
|
|
|
|
goto stop;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clear pending SIGCONT on stop signals */
|
2014-11-29 04:46:13 +08:00
|
|
|
if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN
|
|
|
|
|| si.si_signo == SIGTTOU)
|
2004-01-19 13:46:54 +08:00
|
|
|
sig_clear (SIGCONT);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
if (handler == (void *) SIG_DFL)
|
|
|
|
{
|
2014-11-29 04:46:13 +08:00
|
|
|
if (si.si_signo == SIGCHLD || si.si_signo == SIGIO
|
|
|
|
|| si.si_signo == SIGCONT || si.si_signo == SIGWINCH
|
2004-01-19 13:46:54 +08:00
|
|
|
|| si.si_signo == SIGURG)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2019-01-13 04:19:52 +08:00
|
|
|
if (si.si_code == SI_TIMER)
|
2019-01-22 22:23:05 +08:00
|
|
|
((timer_tracker *) si.si_tid)->disarm_overrun_event ();
|
2012-07-30 11:44:40 +08:00
|
|
|
sigproc_printf ("signal %d default is currently ignore", si.si_signo);
|
2000-02-18 03:38:33 +08:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2014-11-29 04:46:13 +08:00
|
|
|
if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN
|
|
|
|
|| si.si_signo == SIGTTOU)
|
2000-02-18 03:38:33 +08:00
|
|
|
goto stop;
|
|
|
|
|
|
|
|
goto exit_sig;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handler == (void *) SIG_ERR)
|
|
|
|
goto exit_sig;
|
|
|
|
|
|
|
|
goto dosig;
|
|
|
|
|
2003-09-09 11:11:31 +08:00
|
|
|
stop:
|
2014-11-29 04:46:13 +08:00
|
|
|
if (tls != _main_tls)
|
|
|
|
{
|
|
|
|
cygheap->unlock_tls (tl_entry);
|
|
|
|
tl_entry = cygheap->find_tls (_main_tls);
|
|
|
|
tls = _main_tls;
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
handler = (void *) sig_handle_tty_stop;
|
2013-03-31 20:35:44 +08:00
|
|
|
thissig = global_sigs[SIGSTOP];
|
2013-01-03 02:34:06 +08:00
|
|
|
goto dosig;
|
|
|
|
|
|
|
|
exit_sig:
|
|
|
|
handler = (void *) signal_exit;
|
|
|
|
thissig.sa_flags |= SA_SIGINFO;
|
2015-07-05 04:49:30 +08:00
|
|
|
/* Don't run signal_exit on alternate stack. */
|
|
|
|
thissig.sa_flags &= ~SA_ONSTACK;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2003-09-09 11:11:31 +08:00
|
|
|
dosig:
|
2013-01-14 14:03:59 +08:00
|
|
|
if (have_execed)
|
|
|
|
{
|
|
|
|
sigproc_printf ("terminating captive process");
|
2022-02-15 22:23:50 +08:00
|
|
|
if (::cygheap->ctty)
|
|
|
|
::cygheap->ctty->cleanup_before_exit ();
|
2013-01-14 14:03:59 +08:00
|
|
|
TerminateProcess (ch_spawn, sigExeced = si.si_signo);
|
|
|
|
}
|
2013-01-03 02:34:06 +08:00
|
|
|
/* Dispatch to the appropriate function. */
|
|
|
|
sigproc_printf ("signal %d, signal handler %p", si.si_signo, handler);
|
|
|
|
rc = setup_handler (handler, thissig, tls);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2003-09-09 11:11:31 +08:00
|
|
|
done:
|
2014-11-29 04:46:13 +08:00
|
|
|
cygheap->unlock_tls (tl_entry);
|
2000-02-18 03:38:33 +08:00
|
|
|
sigproc_printf ("returning %d", rc);
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-07-05 04:49:30 +08:00
|
|
|
static void
|
|
|
|
altstack_wrapper (int sig, siginfo_t *siginfo, ucontext_t *sigctx,
|
|
|
|
void (*handler) (int, siginfo_t *, void *))
|
|
|
|
{
|
|
|
|
siginfo_t si = *siginfo;
|
|
|
|
ULONG guard_size = 0;
|
|
|
|
DWORD old_prot = (DWORD) -1;
|
|
|
|
PTEB teb = NtCurrentTeb ();
|
|
|
|
PVOID old_limit = NULL;
|
|
|
|
|
|
|
|
/* Check if we're just handling a stack overflow. If so... */
|
|
|
|
if (sig == SIGSEGV && si.si_cyg
|
|
|
|
&& ((cygwin_exception *) si.si_cyg)->exception_record ()->ExceptionCode
|
|
|
|
== (DWORD) STATUS_STACK_OVERFLOW)
|
|
|
|
{
|
|
|
|
/* ...restore guard pages in original stack as if MSVCRT::_resetstkovlw
|
|
|
|
has been called.
|
|
|
|
|
2015-12-15 23:00:20 +08:00
|
|
|
Compute size of guard pages. If SetThreadStackGuarantee returns 0,
|
|
|
|
use the default guard page size. */
|
|
|
|
SetThreadStackGuarantee (&guard_size);
|
2015-07-05 04:49:30 +08:00
|
|
|
if (!guard_size)
|
|
|
|
guard_size = wincap.def_guard_page_size ();
|
|
|
|
else
|
|
|
|
guard_size += wincap.page_size ();
|
|
|
|
old_limit = teb->Tib.StackLimit;
|
|
|
|
/* Amazing but true: This VirtualProtect call automatically fixes the
|
|
|
|
value of teb->Tib.StackLimit on some systems.*/
|
|
|
|
if (VirtualProtect (teb->Tib.StackLimit, guard_size,
|
|
|
|
PAGE_READWRITE | PAGE_GUARD, &old_prot)
|
|
|
|
&& old_limit == teb->Tib.StackLimit)
|
|
|
|
teb->Tib.StackLimit = (caddr_t) old_limit + guard_size;
|
|
|
|
}
|
|
|
|
handler (sig, &si, sigctx);
|
|
|
|
if (old_prot != (DWORD) -1)
|
|
|
|
{
|
|
|
|
/* Typically the handler would exit or at least perform a siglongjmp
|
|
|
|
trying to overcome a SEGV condition. However, if we return from a
|
|
|
|
segv handler after a stack overflow, we're dead. While on Linux the
|
|
|
|
process returns to the offending code and thus the handler is called
|
|
|
|
ad infinitum, on Windows the NTDLL::__stkchk function will simply kill
|
|
|
|
the process. So what we do here is to remove the guard pages again so
|
|
|
|
we can return to exception::handle. exception::handle will then call
|
|
|
|
sig_send again, this time with SIG_DFL action, so at least we get a
|
|
|
|
stackdump. */
|
|
|
|
if (VirtualProtect ((caddr_t) teb->Tib.StackLimit - guard_size,
|
|
|
|
guard_size, old_prot, &old_prot))
|
|
|
|
teb->Tib.StackLimit = old_limit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-02-12 11:01:58 +08:00
|
|
|
int
|
|
|
|
_cygtls::call_signal_handler ()
|
2001-04-02 08:18:29 +08:00
|
|
|
{
|
2011-12-05 01:58:24 +08:00
|
|
|
int this_sa_flags = SA_RESTART;
|
|
|
|
while (1)
|
2001-09-12 13:09:24 +08:00
|
|
|
{
|
2005-12-24 06:50:20 +08:00
|
|
|
lock ();
|
2012-07-30 05:43:29 +08:00
|
|
|
if (!sig)
|
|
|
|
{
|
|
|
|
unlock ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-08-03 23:38:59 +08:00
|
|
|
/* Pop the stack if the next "return address" is sigdelayed, since
|
|
|
|
this function is doing what sigdelayed would have done anyway. */
|
2015-06-19 21:58:23 +08:00
|
|
|
if (retaddr () == (__tlsstack_t) sigdelayed)
|
2011-12-05 01:58:24 +08:00
|
|
|
pop ();
|
|
|
|
|
2019-08-16 22:36:20 +08:00
|
|
|
debug_only_printf ("dealing with signal %d", sig);
|
2004-02-12 11:01:58 +08:00
|
|
|
this_sa_flags = sa_flags;
|
2013-01-31 13:26:47 +08:00
|
|
|
|
2015-04-03 01:15:07 +08:00
|
|
|
sigset_t this_oldmask = set_process_mask_delta ();
|
|
|
|
|
2019-01-13 04:19:52 +08:00
|
|
|
if (infodata.si_code == SI_TIMER)
|
|
|
|
{
|
|
|
|
timer_tracker *tt = (timer_tracker *)
|
|
|
|
infodata.si_tid;
|
2019-01-22 22:23:05 +08:00
|
|
|
infodata.si_overrun = tt->disarm_overrun_event ();
|
2019-01-13 04:19:52 +08:00
|
|
|
}
|
|
|
|
|
2013-01-31 13:26:47 +08:00
|
|
|
/* Save information locally on stack to pass to handler. */
|
2004-02-12 11:01:58 +08:00
|
|
|
int thissig = sig;
|
2013-01-31 13:26:47 +08:00
|
|
|
siginfo_t thissi = infodata;
|
|
|
|
void (*thisfunc) (int, siginfo_t *, void *) = func;
|
2004-01-14 23:45:37 +08:00
|
|
|
|
2019-04-05 17:25:19 +08:00
|
|
|
ucontext_t *thiscontext = NULL, context_copy;
|
2015-04-03 01:15:07 +08:00
|
|
|
|
2019-08-16 22:36:20 +08:00
|
|
|
/* Only make a context for SA_SIGINFO handlers */
|
|
|
|
if (this_sa_flags & SA_SIGINFO)
|
2015-04-04 23:19:31 +08:00
|
|
|
{
|
2015-04-03 01:15:07 +08:00
|
|
|
context.uc_link = 0;
|
|
|
|
context.uc_flags = 0;
|
|
|
|
if (thissi.si_cyg)
|
2015-06-19 22:12:10 +08:00
|
|
|
memcpy (&context.uc_mcontext,
|
|
|
|
((cygwin_exception *) thissi.si_cyg)->context (),
|
|
|
|
sizeof (CONTEXT));
|
2015-04-03 01:15:07 +08:00
|
|
|
else
|
|
|
|
{
|
2015-07-18 00:29:52 +08:00
|
|
|
/* Software-generated signal. We're fetching the current
|
|
|
|
context, unwind to the caller and in case we're called
|
2022-05-17 20:12:32 +08:00
|
|
|
from sigdelayed, fix the instruction pointer accordingly. */
|
2015-04-03 01:15:07 +08:00
|
|
|
context.uc_mcontext.ctxflags = CONTEXT_FULL;
|
2015-07-18 00:29:52 +08:00
|
|
|
RtlCaptureContext ((PCONTEXT) &context.uc_mcontext);
|
|
|
|
__unwind_single_frame ((PCONTEXT) &context.uc_mcontext);
|
|
|
|
if (stackptr > stack)
|
|
|
|
{
|
|
|
|
#ifdef __x86_64__
|
|
|
|
context.uc_mcontext.rip = retaddr ();
|
|
|
|
#else
|
2022-05-17 20:12:32 +08:00
|
|
|
#error unimplemented for this target
|
2015-07-18 00:29:52 +08:00
|
|
|
#endif
|
|
|
|
}
|
2015-04-03 01:15:07 +08:00
|
|
|
}
|
2015-03-31 03:31:13 +08:00
|
|
|
|
2015-06-21 02:21:02 +08:00
|
|
|
if (this_sa_flags & SA_ONSTACK
|
|
|
|
&& !_my_tls.altstack.ss_flags
|
|
|
|
&& _my_tls.altstack.ss_sp)
|
|
|
|
{
|
|
|
|
context.uc_stack = _my_tls.altstack;
|
|
|
|
context.uc_stack.ss_flags = SS_ONSTACK;
|
|
|
|
}
|
2015-04-03 01:15:07 +08:00
|
|
|
else
|
2015-06-21 02:21:02 +08:00
|
|
|
{
|
|
|
|
context.uc_stack.ss_sp = NtCurrentTeb ()->Tib.StackBase;
|
|
|
|
context.uc_stack.ss_flags = 0;
|
|
|
|
if (!NtCurrentTeb ()->DeallocationStack)
|
|
|
|
context.uc_stack.ss_size
|
|
|
|
= (uintptr_t) NtCurrentTeb ()->Tib.StackLimit
|
|
|
|
- (uintptr_t) NtCurrentTeb ()->Tib.StackBase;
|
|
|
|
else
|
|
|
|
context.uc_stack.ss_size
|
|
|
|
= (uintptr_t) NtCurrentTeb ()->DeallocationStack
|
|
|
|
- (uintptr_t) NtCurrentTeb ()->Tib.StackBase;
|
|
|
|
}
|
2015-04-03 01:15:07 +08:00
|
|
|
context.uc_sigmask = context.uc_mcontext.oldmask = this_oldmask;
|
|
|
|
|
2015-04-04 23:12:27 +08:00
|
|
|
context.uc_mcontext.cr2 = (thissi.si_signo == SIGSEGV
|
|
|
|
|| thissi.si_signo == SIGBUS)
|
|
|
|
? (uintptr_t) thissi.si_addr : 0;
|
|
|
|
|
2015-04-03 01:15:07 +08:00
|
|
|
thiscontext = &context;
|
2019-04-05 17:25:19 +08:00
|
|
|
context_copy = context;
|
2015-04-03 01:15:07 +08:00
|
|
|
}
|
2015-03-31 03:31:13 +08:00
|
|
|
|
2004-02-12 11:01:58 +08:00
|
|
|
int this_errno = saved_errno;
|
2012-07-30 05:43:29 +08:00
|
|
|
reset_signal_arrived ();
|
2013-04-09 09:01:19 +08:00
|
|
|
incyg = false;
|
|
|
|
sig = 0; /* Flag that we can accept another signal */
|
2013-01-31 13:26:47 +08:00
|
|
|
unlock (); /* unlock signal stack */
|
|
|
|
|
2015-06-21 02:21:02 +08:00
|
|
|
/* Alternate signal stack requested for this signal and alternate signal
|
|
|
|
stack set up for this thread? */
|
|
|
|
if (this_sa_flags & SA_ONSTACK
|
|
|
|
&& !_my_tls.altstack.ss_flags
|
|
|
|
&& _my_tls.altstack.ss_sp)
|
|
|
|
{
|
|
|
|
/* Yes, use alternate signal stack.
|
|
|
|
|
|
|
|
NOTE:
|
|
|
|
|
|
|
|
We DO NOT change the TEB's stack addresses and we DO NOT move the
|
2022-07-15 00:32:53 +08:00
|
|
|
_cygtls area to the alternate stack. This seems to work fine,
|
|
|
|
but there may be Windows functions not working correctly under
|
|
|
|
these circumstances.
|
2015-06-21 02:21:02 +08:00
|
|
|
|
|
|
|
On the other hand, if a Windows function crashed and we're handling
|
|
|
|
this here, moving the TEB stack addresses may be fatal.
|
|
|
|
|
|
|
|
If the current code does not work as expected in the "usual"
|
|
|
|
POSIX circumstances, this problem must be revisited. */
|
|
|
|
|
2015-06-21 19:58:57 +08:00
|
|
|
/* Compute new stackbase. We start from the high address, aligned
|
|
|
|
to 16 byte. */
|
2015-07-05 04:49:30 +08:00
|
|
|
uintptr_t new_sp = ((uintptr_t) _my_tls.altstack.ss_sp
|
|
|
|
+ _my_tls.altstack.ss_size) & ~0xf;
|
2015-06-21 19:58:57 +08:00
|
|
|
/* In assembler: Save regs on new stack, move to alternate stack,
|
|
|
|
call thisfunc, revert stack regs. */
|
2015-06-21 02:21:02 +08:00
|
|
|
#ifdef __x86_64__
|
2015-06-22 19:09:55 +08:00
|
|
|
/* Clobbered regs: rcx, rdx, r8, r9, r10, r11, rbp, rsp */
|
2015-06-21 02:21:02 +08:00
|
|
|
__asm__ ("\n\
|
2015-06-22 19:09:55 +08:00
|
|
|
movq %[NEW_SP], %%rax # Load alt stack into rax \n\
|
|
|
|
subq $0x60, %%rax # Make room on alt stack \n\
|
|
|
|
# for clobbered regs and \n\
|
|
|
|
# required shadow space \n\
|
|
|
|
movq %%rcx, 0x20(%%rax)# Save clobbered regs \n\
|
|
|
|
movq %%rdx, 0x28(%%rax) \n\
|
|
|
|
movq %%r8, 0x30(%%rax) \n\
|
|
|
|
movq %%r9, 0x38(%%rax) \n\
|
|
|
|
movq %%r10, 0x40(%%rax) \n\
|
|
|
|
movq %%r11, 0x48(%%rax) \n\
|
|
|
|
movq %%rbp, 0x50(%%rax) \n\
|
|
|
|
movq %%rsp, 0x58(%%rax) \n\
|
2015-06-21 02:21:02 +08:00
|
|
|
movl %[SIG], %%ecx # thissig to 1st arg reg \n\
|
2015-06-22 19:09:55 +08:00
|
|
|
leaq %[SI], %%rdx # &thissi to 2nd arg reg \n\
|
2015-06-21 02:21:02 +08:00
|
|
|
movq %[CTX], %%r8 # thiscontext to 3rd arg reg \n\
|
2015-06-22 19:09:55 +08:00
|
|
|
movq %[FUNC], %%r9 # thisfunc to r9 \n\
|
2015-07-05 04:49:30 +08:00
|
|
|
leaq %[WRAPPER], %%r10 # wrapper address to r10 \n\
|
2015-06-22 19:09:55 +08:00
|
|
|
movq %%rax, %%rsp # Move alt stack into rsp \n\
|
2015-07-05 04:49:30 +08:00
|
|
|
call *%%r10 # Call wrapper \n\
|
2015-06-22 19:09:55 +08:00
|
|
|
movq %%rsp, %%rax # Restore clobbered regs \n\
|
|
|
|
movq 0x58(%%rax), %%rsp \n\
|
|
|
|
movq 0x50(%%rax), %%rbp \n\
|
|
|
|
movq 0x48(%%rax), %%r11 \n\
|
|
|
|
movq 0x40(%%rax), %%r10 \n\
|
|
|
|
movq 0x38(%%rax), %%r9 \n\
|
|
|
|
movq 0x30(%%rax), %%r8 \n\
|
|
|
|
movq 0x28(%%rax), %%rdx \n\
|
|
|
|
movq 0x20(%%rax), %%rcx \n"
|
2015-06-21 02:21:02 +08:00
|
|
|
: : [NEW_SP] "o" (new_sp),
|
|
|
|
[SIG] "o" (thissig),
|
2015-06-22 19:09:55 +08:00
|
|
|
[SI] "o" (thissi),
|
2015-06-21 02:21:02 +08:00
|
|
|
[CTX] "o" (thiscontext),
|
2015-07-05 04:49:30 +08:00
|
|
|
[FUNC] "o" (thisfunc),
|
|
|
|
[WRAPPER] "o" (altstack_wrapper)
|
2015-06-21 02:21:02 +08:00
|
|
|
: "memory");
|
|
|
|
#else
|
2022-05-17 20:12:32 +08:00
|
|
|
#error unimplemented for this target
|
2015-06-21 02:21:02 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
/* No alternate signal stack requested or available, just call
|
|
|
|
signal handler. */
|
|
|
|
thisfunc (thissig, &thissi, thiscontext);
|
|
|
|
|
2011-12-05 01:58:24 +08:00
|
|
|
incyg = true;
|
2013-01-31 13:26:47 +08:00
|
|
|
|
2019-04-04 00:14:30 +08:00
|
|
|
set_signal_mask (_my_tls.sigmask, (this_sa_flags & SA_SIGINFO)
|
|
|
|
? context.uc_sigmask : this_oldmask);
|
2003-11-29 04:55:59 +08:00
|
|
|
if (this_errno >= 0)
|
|
|
|
set_errno (this_errno);
|
2019-04-05 17:25:19 +08:00
|
|
|
if (this_sa_flags & SA_SIGINFO)
|
|
|
|
{
|
|
|
|
/* If more than just the sigmask in the context has been changed by
|
|
|
|
the signal handler, call setcontext. */
|
|
|
|
context_copy.uc_sigmask = context.uc_sigmask;
|
|
|
|
if (memcmp (&context, &context_copy, sizeof context) != 0)
|
|
|
|
setcontext (&context);
|
|
|
|
}
|
2001-09-12 13:09:24 +08:00
|
|
|
}
|
|
|
|
|
2015-06-15 22:15:37 +08:00
|
|
|
/* FIXME: Since 2011 this return statement always returned 1 (meaning
|
|
|
|
SA_RESTART is effective) if the thread we're running in is not the
|
|
|
|
main thread. We're disabling this check to enable EINTR behaviour
|
|
|
|
on system calls not running in the main thread. It's not quite clear
|
|
|
|
if that has undesired side-effects, therefore this comment. */
|
|
|
|
return this_sa_flags & SA_RESTART;
|
2001-04-02 08:18:29 +08:00
|
|
|
}
|
2001-04-01 13:38:08 +08:00
|
|
|
|
2006-02-07 02:24:11 +08:00
|
|
|
void
|
2013-03-10 05:55:18 +08:00
|
|
|
_cygtls::signal_debugger (siginfo_t& si)
|
2006-02-07 02:24:11 +08:00
|
|
|
{
|
2014-03-30 05:16:09 +08:00
|
|
|
HANDLE th;
|
|
|
|
/* If si.si_cyg is set then the signal was already sent to the debugger. */
|
|
|
|
if (isinitialized () && !si.si_cyg && (th = (HANDLE) *this)
|
|
|
|
&& being_debugged () && SuspendThread (th) >= 0)
|
2006-02-07 02:24:11 +08:00
|
|
|
{
|
2013-03-10 05:55:18 +08:00
|
|
|
CONTEXT c;
|
2014-03-30 05:16:09 +08:00
|
|
|
c.ContextFlags = CONTEXT_FULL;
|
|
|
|
if (GetThreadContext (th, &c))
|
2013-03-10 05:55:18 +08:00
|
|
|
{
|
|
|
|
if (incyg)
|
2022-05-17 20:12:32 +08:00
|
|
|
c._CX_instPtr = retaddr ();
|
2015-07-05 04:49:30 +08:00
|
|
|
memcpy (&context.uc_mcontext, &c, sizeof (CONTEXT));
|
2022-07-15 00:32:53 +08:00
|
|
|
/* Enough space for 64 bit addresses */
|
2015-06-19 22:12:10 +08:00
|
|
|
char sigmsg[2 * sizeof (_CYGWIN_SIGNAL_STRING
|
|
|
|
" ffffffff ffffffffffffffff")];
|
|
|
|
__small_sprintf (sigmsg, _CYGWIN_SIGNAL_STRING " %d %y %p",
|
2015-07-05 04:49:30 +08:00
|
|
|
si.si_signo, thread_id, &context.uc_mcontext);
|
2014-03-30 05:16:09 +08:00
|
|
|
OutputDebugString (sigmsg);
|
2013-03-10 05:55:18 +08:00
|
|
|
}
|
2014-03-30 05:16:09 +08:00
|
|
|
ResumeThread (th);
|
2006-02-07 02:24:11 +08:00
|
|
|
}
|
|
|
|
}
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
|
|
|
|
extern "C" int
|
|
|
|
setcontext (const ucontext_t *ucp)
|
|
|
|
{
|
|
|
|
PCONTEXT ctx = (PCONTEXT) &ucp->uc_mcontext;
|
2019-04-05 18:13:44 +08:00
|
|
|
set_signal_mask (_my_tls.sigmask, ucp->uc_sigmask);
|
2019-04-05 03:25:47 +08:00
|
|
|
_my_tls.incyg = true;
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
RtlRestoreContext (ctx, NULL);
|
|
|
|
/* If we got here, something was wrong. */
|
|
|
|
set_errno (EINVAL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int
|
|
|
|
getcontext (ucontext_t *ucp)
|
|
|
|
{
|
|
|
|
PCONTEXT ctx = (PCONTEXT) &ucp->uc_mcontext;
|
|
|
|
ctx->ContextFlags = CONTEXT_FULL;
|
|
|
|
RtlCaptureContext (ctx);
|
|
|
|
__unwind_single_frame (ctx);
|
2022-05-17 20:12:32 +08:00
|
|
|
/* Successful getcontext is supposed to return 0. If we don't set the
|
|
|
|
return register to 0 here, there's a chance that code like this:
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
|
|
|
|
if (getcontext (&ctx) != 0)
|
|
|
|
|
2022-05-17 20:12:32 +08:00
|
|
|
assumes that getcontext failed after calling setcontext (&ctx). */
|
|
|
|
ucp->uc_mcontext._MC_retReg = 0;
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
ucp->uc_sigmask = ucp->uc_mcontext.oldmask = _my_tls.sigmask;
|
|
|
|
/* Do not touch any other member of ucontext_t. */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int
|
|
|
|
swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
|
|
|
|
{
|
|
|
|
PCONTEXT ctx = (PCONTEXT) &oucp->uc_mcontext;
|
|
|
|
ctx->ContextFlags = CONTEXT_FULL;
|
|
|
|
RtlCaptureContext (ctx);
|
|
|
|
__unwind_single_frame (ctx);
|
2015-07-17 22:47:14 +08:00
|
|
|
/* See comment in getcontext. */
|
2022-05-17 20:12:32 +08:00
|
|
|
oucp->uc_mcontext._MC_retReg = 0;
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
oucp->uc_sigmask = oucp->uc_mcontext.oldmask = _my_tls.sigmask;
|
|
|
|
return setcontext (ucp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Trampoline function to set the context to uc_link. The pointer to the
|
2022-05-17 20:12:32 +08:00
|
|
|
address of uc_link is stored in a callee-saved register, referenced by
|
|
|
|
_MC_uclinkReg from the C code. If uc_link is NULL, call exit. */
|
|
|
|
#ifdef __x86_64__
|
|
|
|
/* _MC_uclinkReg == %rbx */
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
__asm__ (" \n\
|
|
|
|
.global __cont_link_context \n\
|
2015-07-24 02:25:22 +08:00
|
|
|
.seh_proc __cont_link_context \n\
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
__cont_link_context: \n\
|
2015-07-24 02:25:22 +08:00
|
|
|
.seh_endprologue \n\
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
movq %rbx, %rsp \n\
|
2015-07-24 02:25:22 +08:00
|
|
|
movq (%rsp), %rcx \n\
|
|
|
|
# align stack and subtract shadow space \n\
|
|
|
|
andq $~0xf, %rsp \n\
|
|
|
|
subq $0x20, %rsp \n\
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
testq %rcx, %rcx \n\
|
|
|
|
je 1f \n\
|
|
|
|
call setcontext \n\
|
|
|
|
movq $0xff, %rcx \n\
|
|
|
|
1: \n\
|
|
|
|
call cygwin_exit \n\
|
|
|
|
nop \n\
|
2015-07-24 02:25:22 +08:00
|
|
|
.seh_endproc \n\
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
");
|
|
|
|
|
|
|
|
#else
|
2022-05-17 20:12:32 +08:00
|
|
|
#error unimplemented for this target
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* makecontext is modelled after GLibc's makecontext. The stack from uc_stack
|
|
|
|
is prepared so that it starts with a pointer to the linked context uc_link,
|
|
|
|
followed by the arguments to func, and finally at the bottom the "return"
|
|
|
|
address set to __cont_link_context. In the ucp context, rbx/ebx is set to
|
|
|
|
point to the stack address where the pointer to uc_link is stored. The
|
|
|
|
requirement to make this work is that rbx/ebx are callee-saved registers
|
|
|
|
per the ABI. If any function is called which doesn't follow the ABI
|
|
|
|
conventions, e.g. assembler code, this method will break. But that's ok. */
|
|
|
|
extern "C" void
|
|
|
|
makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
|
|
|
|
{
|
|
|
|
extern void __cont_link_context (void);
|
|
|
|
uintptr_t *sp;
|
|
|
|
va_list ap;
|
|
|
|
|
2015-07-18 18:35:23 +08:00
|
|
|
/* Initialize sp to the top of the stack. */
|
|
|
|
sp = (uintptr_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
|
|
|
|
/* Subtract slots required for arguments and the pointer to uc_link. */
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
sp -= (argc + 1);
|
2015-07-18 18:35:23 +08:00
|
|
|
/* Align. */
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
sp = (uintptr_t *) ((uintptr_t) sp & ~0xf);
|
2015-07-18 18:35:23 +08:00
|
|
|
/* Subtract one slot for setting the return address. */
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
--sp;
|
2015-07-18 18:35:23 +08:00
|
|
|
/* Set return address to the trampolin function __cont_link_context. */
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
sp[0] = (uintptr_t) __cont_link_context;
|
2015-07-18 18:35:23 +08:00
|
|
|
/* Fetch arguments and store them on the stack.
|
|
|
|
|
2022-05-17 20:12:32 +08:00
|
|
|
x86_64:
|
2015-07-18 18:35:23 +08:00
|
|
|
|
|
|
|
- Store first four args in the AMD64 ABI arg registers.
|
|
|
|
|
|
|
|
- Note that the stack is not short by these four register args. The
|
|
|
|
reason is the shadow space for these regs required by the AMD64 ABI.
|
|
|
|
|
|
|
|
- The definition of makecontext only allows for "int" sized arguments to
|
|
|
|
func, 32 bit, likely for historical reasons. However, the argument
|
|
|
|
slots on x86_64 are 64 bit anyway, so we can fetch and store the args
|
|
|
|
as 64 bit values, and func can request 64 bit args without violating
|
|
|
|
the definition. This potentially allows porting 32 bit applications
|
|
|
|
providing pointer values to func without additional porting effort. */
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
va_start (ap, argc);
|
|
|
|
for (int i = 0; i < argc; ++i)
|
|
|
|
#ifdef __x86_64__
|
|
|
|
switch (i)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
ucp->uc_mcontext.rcx = va_arg (ap, uintptr_t);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
ucp->uc_mcontext.rdx = va_arg (ap, uintptr_t);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ucp->uc_mcontext.r8 = va_arg (ap, uintptr_t);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
ucp->uc_mcontext.r9 = va_arg (ap, uintptr_t);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sp[i + 1] = va_arg (ap, uintptr_t);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#else
|
2022-05-17 20:12:32 +08:00
|
|
|
#error unimplemented for this target
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
#endif
|
|
|
|
va_end (ap);
|
2015-07-18 18:35:23 +08:00
|
|
|
/* Store pointer to uc_link at the top of the stack. */
|
|
|
|
sp[argc + 1] = (uintptr_t) ucp->uc_link;
|
|
|
|
/* Last but not least set the register in the context at ucp so that a
|
|
|
|
subsequent setcontext or swapcontext picks up the right values:
|
2022-05-17 20:12:32 +08:00
|
|
|
- Set instruction pointer to the target function.
|
|
|
|
- Set stack pointer to the just computed stack pointer value.
|
|
|
|
- Set Cygwin-specific uclink register to the address of the pointer
|
|
|
|
to uc_link. */
|
|
|
|
ucp->uc_mcontext._MC_instPtr = (uint64_t) func;
|
|
|
|
ucp->uc_mcontext._MC_stackPtr = (uint64_t) sp;
|
|
|
|
ucp->uc_mcontext._MC_uclinkReg = (uint64_t) (sp + argc + 1);
|
Implement getcontext, setcontext, makecontext, swapcontext
* common.din (getcontext): Export.
(makecontext): Export.
(setcontext): Export.
(swapcontext): Export.
* exceptions.cc (__unwind_single_frame): New static functions, 64 bit
only.
(setcontext): New function.
(getcontext): New function.
(swapcontext): New function.
(__cont_link_context): New function.
(makecontext): New function.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2002.
(CYGWIN_VERSION_API_MINOR): Bump.
* include/ucontext.h (getcontext): Add prototype.
(setcontext): Ditto.
(swapcontext): Ditto.
(makecontext): Ditto.
* ntdll.h (NtContinue): Ditto.
* new-features.xml (ov-new2.2): Add new section. Document getcontext,
setcontext, makecontext, swapcontext.
* posix.xml (std-deprec): Add getcontext, setcontext, makecontext,
swapcontext.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2015-07-17 20:31:12 +08:00
|
|
|
}
|