signlwnt.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 295 行
C
295 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Windows NT signal handling (based on OS provided exception
* handling).
*
****************************************************************************/
#include "variety.h"
#include <signal.h>
#include <errno.h>
#include <float.h>
#include <windows.h>
#include <excpt.h>
#include "rtdata.h"
#include "sigtab.h"
#include "sigfunc.h"
#include "seterrno.h"
#include "signlwnt.h"
#include "rtinit.h"
_WCRTLINK extern void (*__sig_init_rtn)( void );
_WCRTLINK extern void (*__sig_fini_rtn)( void );
sigtab SignalTable[] = {
{ SIG_IGN, -1 }, /* unused */
{ SIG_DFL, -1 }, /* SIGABRT */
{ SIG_DFL, -1 }, /* SIGFPE */
{ SIG_DFL, STATUS_ILLEGAL_INSTRUCTION }, /* SIGILL */
{ SIG_DFL, STATUS_CONTROL_C_EXIT }, /* SIGINT */
{ SIG_DFL, STATUS_ACCESS_VIOLATION }, /* SIGSEGV */
{ SIG_DFL, STATUS_CONTROL_C_EXIT }, /* SIGTERM */
{ SIG_DFL, STATUS_CONTROL_C_EXIT }, /* SIGBREAK */
{ SIG_IGN, -1 }, /* SIGUSR1 */
{ SIG_IGN, -1 }, /* SIGUSR2 */
{ SIG_IGN, -1 }, /* SIGUSR3 */
{ SIG_DFL, STATUS_INTEGER_DIVIDE_BY_ZERO }, /* SIGIDIVZ */
{ SIG_DFL, STATUS_INTEGER_OVERFLOW } /* SIGIOVFL */
};
static char CtrlHandlerRunning = FALSE;
__sig_func __SetSignalFunc( int sig, __sig_func new_func )
{
__sig_func prev_func = NULL;
if(( sig == SIGBREAK ) || ( sig == SIGINT )) {
prev_func = SignalTable[ sig ].func;
SignalTable[ sig ].func = new_func;
} else {
prev_func = _RWD_sigtab[ sig ].func;
_RWD_sigtab[ sig ].func = new_func;
}
return( prev_func );
}
__sig_func __GetSignalFunc( int sig )
{
if(( sig == SIGBREAK ) || ( sig == SIGINT ))
return( SignalTable[ sig ].func );
return( _RWD_sigtab[ sig ].func );
}
long __GetSignalOSCode( int sig )
{
if(( sig == SIGBREAK ) || ( sig == SIGINT ))
return( SignalTable[ sig ].os_sig_code );
return( _RWD_sigtab[ sig ].os_sig_code );
}
__sig_func __CheckSignalExCode( int sig, long code )
{
if( code == __GetSignalOSCode( sig ) )
return( __GetSignalFunc( sig ) );
return( NULL );
}
static BOOL WINAPI CtrlSignalHandler( IN ULONG Event )
{
__sig_func func;
switch( Event ) {
case CTRL_C_EVENT:
func = __GetSignalFunc( SIGINT );
if( !func )
return( FALSE );
raise( SIGINT );
break;
case CTRL_BREAK_EVENT:
func = __GetSignalFunc( SIGBREAK );
if( !func )
return( FALSE );
raise( SIGBREAK );
break;
default:
return( FALSE );
}
if(( func == SIG_DFL ) || ( func == SIG_ERR ))
return( FALSE );
return( TRUE );
}
static BOOL CtrlHandlerIsNeeded( void )
{
__sig_func int_func = __GetSignalFunc( SIGINT );
__sig_func brk_func = __GetSignalFunc( SIGBREAK );
return((( int_func != SIG_DFL ) && ( int_func != SIG_ERR ))
|| (( brk_func != SIG_DFL ) && ( brk_func != SIG_ERR )));
}
static BOOL StartCtrlHandler( void )
{
if( !CtrlHandlerRunning && SetConsoleCtrlHandler( CtrlSignalHandler, TRUE ) )
CtrlHandlerRunning = TRUE;
return( (BOOL)CtrlHandlerRunning );
}
static BOOL KillCtrlHandler( void )
{
if( CtrlHandlerRunning && SetConsoleCtrlHandler( CtrlSignalHandler, FALSE ) )
CtrlHandlerRunning = FALSE;
return( !(BOOL)CtrlHandlerRunning );
}
void __sigabort( void )
{
raise( SIGABRT );
}
_WCRTLINK int __sigfpe_handler( int fpe )
{
__sig_func func;
func = __GetSignalFunc( SIGFPE );
if(( func != SIG_IGN ) && ( func != SIG_DFL ) && ( func != SIG_ERR )) {
__SetSignalFunc( SIGFPE, SIG_DFL );
(*(__sigfpe_func)func)( SIGFPE, fpe );
return( 0 );
} else if( func == SIG_IGN ) {
return( 0 );
}
return( -1 );
}
_WCRTLINK __sig_func signal( int sig, __sig_func func )
{
__sig_func prev_func;
if(( sig < 1 ) || ( sig > __SIGLAST )) {
__set_errno( EINVAL );
return( SIG_ERR );
}
_RWD_abort = __sigabort; /* change the abort rtn address */
prev_func = __GetSignalFunc( sig );
__SetSignalFunc( sig, func );
if( CtrlHandlerIsNeeded() )
StartCtrlHandler();
else
KillCtrlHandler();
return( prev_func );
}
_WCRTLINK int raise( int sig )
{
__sig_func func;
func = __GetSignalFunc( sig );
switch( sig ) {
case SIGFPE:
__sigfpe_handler( FPE_EXPLICITGEN );
break;
case SIGABRT:
if( func == SIG_DFL ) {
__terminate();
}
case SIGILL:
case SIGINT:
case SIGSEGV:
case SIGTERM:
case SIGBREAK:
case SIGUSR1:
case SIGUSR2:
case SIGUSR3:
case SIGIDIVZ:
case SIGIOVFL:
if(( func != SIG_IGN ) && ( func != SIG_DFL ) && ( func != SIG_ERR )) {
__SetSignalFunc( sig, SIG_DFL );
(*func)( sig );
}
/*
* If the CtrlSignalHandler was needed before we processed the
* signal but is not needed NOW then we need to remove it since it
* has just now become unnecessary.
*
* NOTE: This MAY be a bad thing to do since raise() might have been
* called from within CtrlSignalHandler() in which case we are
* removing the handler from within the handler. Does NT care?
*/
if( !CtrlHandlerIsNeeded() )
KillCtrlHandler();
break;
default:
return( -1 );
}
return( 0 );
}
void __SigInit( void )
{
#if defined( __SW_BM )
int i;
for( i = 1; i <= __SIGLAST; ++i ) {
_RWD_sigtab[ i ] = SignalTable[ i ];
}
#endif
__oscode_check_func = __CheckSignalExCode;
__raise_func = raise;
}
void __SigFini( void )
{
/*
* If there are still SIGINT or SIGBREAK handlers in the sig table,
* then the CtrlSignalHandler is still loaded and we want to get
* rid of it.
*/
if( CtrlHandlerIsNeeded() ) {
KillCtrlHandler();
__SetSignalFunc( SIGINT, SIG_DFL );
__SetSignalFunc( SIGBREAK, SIG_DFL );
}
}
void __sig_init( void )
{
__sig_init_rtn = __SigInit;
__sig_fini_rtn = __SigFini;
_RWD_FPE_handler = (FPEhandler *)__sigfpe_handler;
}
AXI( __sig_init, INIT_PRIORITY_LIBRARY )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?