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 */