File: SigHandler.cpp

package info (click to toggle)
libassa 3.5.0-1
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 3,084 kB
  • ctags: 2,323
  • sloc: cpp: 15,641; sh: 8,704; makefile: 372; perl: 51
file content (152 lines) | stat: -rw-r--r-- 3,473 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// -*- c++ -*-
//---------------------------------------------------------------------------
//                            SigHandler.cpp
//---------------------------------------------------------------------------
//  Copyright (C) 1997-2002  Vladislav Grinchenko 
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//---------------------------------------------------------------------------
#include <signal.h>

#include "assa/Assure.h"
#include "assa/SigHandler.h"

using namespace ASSA;

#if !defined(WIN32)

/*--- static variables ---*/

EventHandler* SigHandler::m_signal_handlers [NSIG];

int
SigHandler::
in_range (int signum_)
{
	trace_with_mask("SigHandler::in_range", SIGHAND);

	if ( signum_ >= 1 && signum_ < NSIG) {
		return 0;
	}
	else {
		DL((SIGHAND,"signum_ %d is out of range [1;%d]\n", NSIG));
		return -1;
	}
}

EventHandler *
SigHandler::
handler (int signum_, EventHandler* newh_)
{
	trace_with_mask("SigHandler::handler(int, EH*)", SIGHAND);
	

	if (in_range(signum_) == -1)
		return 0;

	EventHandler* oh = m_signal_handlers[signum_];
	m_signal_handlers[signum_] = newh_;

	return oh;
}

EventHandler *
SigHandler::
handler (int signum_)
{
	trace_with_mask("SigHandler::handler", SIGHAND);

	if ( in_range (signum_) == -1 ) 
		return 0;

	return m_signal_handlers[signum_];
}

int 
SigHandler::
install (int signum_, EventHandler *new_hand_, SigAction *new_disp_,
		 EventHandler **old_hand_, SigAction *old_disp_)
{
	trace_with_mask("SigHandler::install", SIGHAND);

	if (in_range (signum_) == -1) 
		return -1;

	/*--- replace old Event Handler ptr with new one in my internal 
	  dispatch table, returning the old one.
	  ---*/
	EventHandler* eh = handler(signum_, new_hand_);
    
	/*--- if I am given place to store, save old handler ---*/
	if (old_hand_ != 0) 
		*old_hand_ = eh;
    
	/*--- retrieve old disposition ---*/
	if (old_disp_ != 0) {
		old_disp_->retrieve_action (signum_);
		old_disp_->handler ((C_SIG_HANDLER) SIG_DFL);
	}
    
	/*--- if new disposition is NULL, use null action instead ---*/
	SigAction null_sa;	
    
	if (new_disp_ == 0) 
		new_disp_ = &null_sa;
    
	/*--- install my dispatcher ---*/
	new_disp_->handler((C_SIG_HANDLER) SigHandler::dispatch);
    
	return new_disp_->register_action(signum_, old_disp_);
}

int
SigHandler::
remove (int signum_, EventHandler* /* eh_ */,
		SigAction *new_disp_,  SigAction *old_disp_)
{
	trace_with_mask("SigHandler::remove", SIGHAND);

	if (in_range(signum_) == -1) 
		return -1;
	/*--- 
	  We need default disposition here if user forgot to give us one.
	  ---*/
	SigAction sa ((C_SIG_HANDLER) SIG_DFL);

	if (new_disp_ == 0) {
		new_disp_ = &sa;
	}

	m_signal_handlers[signum_] = 0;
    
	return new_disp_->register_action (signum_, old_disp_);
}

void 
SigHandler::
dispatch (int signum_)
{
	trace_with_mask("SigHandler::dispatch", SIGHAND);
  
	/*--- save errno ---*/
	int my_errno = errno;

	EventHandler *eh = m_signal_handlers[signum_];

	if (eh != 0 && eh->handle_signal(signum_) == -1) {
		/*--- 
		  we are in trouble, fall back to defaults 
		  ---*/
		SigAction defact((C_SIG_HANDLER) SIG_DFL);
		m_signal_handlers[signum_] = 0;
		defact.register_action(signum_);
	}
	/*--- restore errno ---*/
	errno = my_errno;
}

#endif // !defined(WIN32)