Implement signals.
diff --git a/dlls/msvcrt/except.c b/dlls/msvcrt/except.c index 44ac230..6ba972a 100644 --- a/dlls/msvcrt/except.c +++ b/dlls/msvcrt/except.c
@@ -2,6 +2,7 @@ * msvcrt.dll exception handling * * Copyright 2000 Jon Griffiths + * Copyright 2005 Juan Lang * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -37,12 +38,13 @@ #include "wine/exception.h" #include "msvcrt.h" #include "excpt.h" +#include "wincon.h" +#include "msvcrt/float.h" +#include "msvcrt/signal.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); -typedef void (*MSVCRT_sig_handler_func)(void); - /* VC++ extensions to Win32 SEH */ typedef struct _SCOPETABLE { @@ -385,11 +387,144 @@ } #endif /* i386 */ +static __sighandler_t sighandlers[NSIG] = { SIG_DFL }; + +static BOOL WINAPI msvcrt_console_handler(DWORD ctrlType) +{ + BOOL ret = FALSE; + + switch (ctrlType) + { + case CTRL_C_EVENT: + if (sighandlers[SIGINT]) + { + if (sighandlers[SIGINT] != SIG_IGN) + sighandlers[SIGINT](SIGINT); + ret = TRUE; + } + break; + } + return ret; +} + +typedef void (*float_handler)(int, int); + +/* The exception codes are actually NTSTATUS values */ +struct +{ + NTSTATUS status; + int signal; +} float_exception_map[] = { + { EXCEPTION_FLT_DENORMAL_OPERAND, _FPE_DENORMAL }, + { EXCEPTION_FLT_DIVIDE_BY_ZERO, _FPE_ZERODIVIDE }, + { EXCEPTION_FLT_INEXACT_RESULT, _FPE_INEXACT }, + { EXCEPTION_FLT_INVALID_OPERATION, _FPE_INVALID }, + { EXCEPTION_FLT_OVERFLOW, _FPE_OVERFLOW }, + { EXCEPTION_FLT_STACK_CHECK, _FPE_STACKOVERFLOW }, + { EXCEPTION_FLT_UNDERFLOW, _FPE_UNDERFLOW }, +}; + +static LONG WINAPI msvcrt_exception_filter(struct _EXCEPTION_POINTERS *except) +{ + LONG ret = EXCEPTION_CONTINUE_SEARCH; + + switch (except->ExceptionRecord->ExceptionCode) + { + case EXCEPTION_ACCESS_VIOLATION: + if (sighandlers[SIGSEGV]) + { + if (sighandlers[SIGSEGV] != SIG_IGN) + sighandlers[SIGSEGV](SIGSEGV); + ret = EXCEPTION_CONTINUE_EXECUTION; + } + break; + /* According to + * http://msdn.microsoft.com/library/en-us/vclib/html/_CRT_signal.asp + * the FPE signal handler takes as a second argument the type of + * floating point exception. + */ + case EXCEPTION_FLT_DENORMAL_OPERAND: + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + case EXCEPTION_FLT_INEXACT_RESULT: + case EXCEPTION_FLT_INVALID_OPERATION: + case EXCEPTION_FLT_OVERFLOW: + case EXCEPTION_FLT_STACK_CHECK: + case EXCEPTION_FLT_UNDERFLOW: + if (sighandlers[SIGFPE]) + { + if (sighandlers[SIGFPE] != SIG_IGN) + { + int i, float_signal = _FPE_INVALID; + + float_handler handler = (float_handler)sighandlers[SIGFPE]; + for (i = 0; i < sizeof(float_exception_map) / + sizeof(float_exception_map[0]); i++) + if (float_exception_map[i].status == + except->ExceptionRecord->ExceptionCode) + { + float_signal = float_exception_map[i].signal; + break; + } + handler(SIGFPE, float_signal); + } + ret = EXCEPTION_CONTINUE_EXECUTION; + } + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + if (sighandlers[SIGILL]) + { + if (sighandlers[SIGILL] != SIG_IGN) + sighandlers[SIGILL](SIGILL); + ret = EXCEPTION_CONTINUE_EXECUTION; + } + break; + } + return ret; +} + +void msvcrt_init_signals(void) +{ + SetConsoleCtrlHandler(msvcrt_console_handler, TRUE); + SetUnhandledExceptionFilter(msvcrt_exception_filter); +} + +void msvcrt_free_signals(void) +{ + SetConsoleCtrlHandler(msvcrt_console_handler, FALSE); + SetUnhandledExceptionFilter(NULL); +} + /********************************************************************* * signal (MSVCRT.@) + * MS signal handling is described here: + * http://msdn.microsoft.com/library/en-us/vclib/html/_CRT_signal.asp + * Some signals may never be generated except through an explicit call to + * raise. */ -void* MSVCRT_signal(int sig, MSVCRT_sig_handler_func func) +__sighandler_t MSVCRT_signal(int sig, __sighandler_t func) { - FIXME("(%d %p):stub\n", sig, func); - return (void*)-1; + __sighandler_t ret = SIG_ERR; + + TRACE("(%d, %p)\n", sig, func); + + if (func == SIG_ERR) return SIG_ERR; + + switch (sig) + { + /* Cases handled internally. Note SIGTERM is never generated by Windows, + * so we effectively mask it. + */ + case SIGABRT: + case SIGFPE: + case SIGILL: + case SIGSEGV: + case SIGINT: + case SIGTERM: + ret = sighandlers[sig]; + sighandlers[sig] = func; + break; + default: + ret = SIG_ERR; + } + return ret; }
diff --git a/dlls/msvcrt/main.c b/dlls/msvcrt/main.c index 4297bb8..b8660bb 100644 --- a/dlls/msvcrt/main.c +++ b/dlls/msvcrt/main.c
@@ -51,6 +51,7 @@ msvcrt_init_io(); msvcrt_init_console(); msvcrt_init_args(); + msvcrt_init_signals(); MSVCRT_setlocale(0, "C"); TRACE("finished process init\n"); break; @@ -61,6 +62,7 @@ msvcrt_free_io(); msvcrt_free_console(); msvcrt_free_args(); + msvcrt_free_signals(); if (!msvcrt_free_tls()) return FALSE; TRACE("finished process free\n");
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index b6d4637..03f553d 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h
@@ -125,6 +125,8 @@ extern void msvcrt_free_console(void); extern void msvcrt_init_args(void); extern void msvcrt_free_args(void); +extern void msvcrt_init_signals(void); +extern void msvcrt_free_signals(void); extern unsigned msvcrt_create_io_inherit_block(STARTUPINFOA*);
diff --git a/include/Makefile.in b/include/Makefile.in index 47b9582..a46acd6 100644 --- a/include/Makefile.in +++ b/include/Makefile.in
@@ -291,6 +291,7 @@ msvcrt/search.h \ msvcrt/setjmp.h \ msvcrt/share.h \ + msvcrt/signal.h \ msvcrt/stddef.h \ msvcrt/stdio.h \ msvcrt/stdlib.h \
diff --git a/include/msvcrt/float.h b/include/msvcrt/float.h index 0fa9322..3122093 100644 --- a/include/msvcrt/float.h +++ b/include/msvcrt/float.h
@@ -114,6 +114,19 @@ #define _FPCLASS_PN 0x0100 /* Positive Normal */ #define _FPCLASS_PINF 0x0200 /* Positive Infinity */ +/* floating point error signals */ +#define _FPE_INVALID 0x81 +#define _FPE_DENORMAL 0x82 +#define _FPE_ZERODIVIDE 0x83 +#define _FPE_OVERFLOW 0x84 +#define _FPE_UNDERFLOW 0x85 +#define _FPE_INEXACT 0x86 +#define _FPE_UNEMULATED 0x87 +#define _FPE_SQRTNEG 0x88 +#define _FPE_STACKOVERFLOW 0x8a +#define _FPE_STACKUNDERFLOW 0x8b +#define _FPE_EXPLICITGEN 0x8c + double _copysign (double, double); double _chgsign (double); double _scalb(double, long);
diff --git a/include/msvcrt/signal.h b/include/msvcrt/signal.h new file mode 100644 index 0000000..38a3e58 --- /dev/null +++ b/include/msvcrt/signal.h
@@ -0,0 +1,45 @@ +/* + * Signal definitions + * + * Copyright 2005 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _WINE_SIGNAL_H +#define _WINE_SIGNAL_H +#ifndef __WINE_USE_MSVCRT +#define __WINE_USE_MSVCRT +#endif + +#define SIGINT 2 +#define SIGILL 4 +#define SIGFPE 8 +#define SIGSEGV 11 +#define SIGTERM 15 +#define SIGBREAK 21 +#define SIGABRT 22 + +#define NSIG (SIGABRT + 1) + +typedef void (*__sighandler_t)(int); + +#define SIG_DFL ((__sighandler_t)0) +#define SIG_IGN ((__sighandler_t)1) +#define SIG_ERR ((__sighandler_t)-1) + +__sighandler_t signal(int sig, __sighandler_t func); +int raise(int sig); + +#endif /* _WINE_SIGNAL_H */