OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.61/] [tools/] [src/] [librutiltpp/] [RtclSignalAction.cpp] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 25 wfjm
// $Id: RtclSignalAction.cpp 577 2014-08-03 20:49:42Z mueller $
2 22 wfjm
//
3 25 wfjm
// Copyright 2013-2014 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4 22 wfjm
//
5
// This program is free software; you may redistribute and/or modify it under
6
// the terms of the GNU General Public License as published by the Free
7
// Software Foundation, either version 2, or at your option any later version.
8
//
9
// This program is distributed in the hope that it will be useful, but
10
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
11
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
// for complete details.
13
// 
14
// Revision History: 
15
// Date         Rev Version  Comment
16 25 wfjm
// 2014-08-02   577   1.0.1  add include unistd.h  (write+pipe dcl)
17 22 wfjm
// 2013-05-17   521   1.0    Initial version
18
// ---------------------------------------------------------------------------
19
 
20
/*!
21
  \file
22 25 wfjm
  \version $Id: RtclSignalAction.cpp 577 2014-08-03 20:49:42Z mueller $
23 22 wfjm
  \brief   Implemenation of class RtclSignalAction.
24
 */
25
 
26
#include <errno.h>
27
#include <signal.h>
28
#include <string.h>
29 25 wfjm
#include <unistd.h>
30 22 wfjm
 
31
#include <iostream>
32
 
33
#include "librtools/Rexception.hpp"
34
 
35
#include "RtclSignalAction.hpp"
36
 
37
using namespace std;
38
 
39
/*!
40
  \class Retro::RtclSignalAction
41
  \brief FIXME_docs
42
*/
43
 
44
// all method definitions in namespace Retro
45
namespace Retro {
46
 
47
RtclSignalAction* RtclSignalAction::fpObj = 0;
48
 
49
//------------------------------------------+-----------------------------------
50
//! FIXME_docs
51
bool RtclSignalAction::Init(Tcl_Interp* interp, RerrMsg& emsg)
52
{
53
  if (fpObj) {
54
    emsg.Init("RtclSignalAction::Init", "already initialized");
55
    return false;
56
  }
57
 
58
  try {
59
    fpObj = new RtclSignalAction(interp);
60
  } catch (exception& e) {
61
    emsg.Init("RtclSignalAction::Init", string("exception: ")+e.what());
62
    return false;
63
  }
64
 
65
  Tcl_CreateExitHandler((Tcl_ExitProc*) ThunkTclExitProc, (ClientData) fpObj);
66
 
67
  return true;
68
}
69
 
70
//------------------------------------------+-----------------------------------
71
//! FIXME_docs
72
 
73
RtclSignalAction* RtclSignalAction::Obj()
74
{
75
  return fpObj;
76
}
77
 
78
 
79
//------------------------------------------+-----------------------------------
80
//! FIXME_docs
81
 
82
bool RtclSignalAction::SetAction(int signum, Tcl_Obj* pobj, RerrMsg& emsg)
83
{
84
  if (!ValidSignal(signum, emsg)) return false;
85
  if (fActionSet[signum] && !ClearAction(signum, emsg)) return false;
86
 
87
  struct sigaction sigact;
88
  ::memset(&sigact, 0, sizeof(sigact));
89
  sigact.sa_handler = SignalHandler;
90
 
91
  if (::sigaction(signum, &sigact, &fOldAction[signum]) != 0) {
92
    emsg.InitErrno("RtclSignalAction::SetAction",
93
                   "sigaction() failed: ", errno);
94
    return false;
95
  }
96
 
97
  fpScript[signum] = pobj;
98
  fActionSet[signum] = true;
99
  return true;
100
}
101
 
102
//------------------------------------------+-----------------------------------
103
//! FIXME_docs
104
 
105
bool RtclSignalAction::GetAction(int signum, Tcl_Obj*& pobj, RerrMsg& emsg)
106
{
107
  if (!ValidSignal(signum, emsg)) return false;
108
  if (!fActionSet[signum]) {
109
    emsg.Init("RtclSignalAction::GetAction", "no action for signal");
110
    return false;
111
  }
112
 
113
  pobj = fpScript[signum];
114
  return true;
115
}
116
 
117
//------------------------------------------+-----------------------------------
118
//! FIXME_docs
119
 
120
bool RtclSignalAction::ClearAction(int signum, RerrMsg& emsg)
121
{
122
  if (!ValidSignal(signum, emsg)) return false;
123
  if (!fActionSet[signum]) {
124
    emsg.Init("RtclSignalAction::ClearAction", "no action for signal");
125
    return false;
126
  }
127
 
128
  if (::sigaction(signum, &fOldAction[signum], NULL) != 0) {
129
    emsg.InitErrno("RtclSignalAction::ClearAction",
130
                   "sigaction() failed: ", errno);
131
    return false;
132
  }
133
  fpScript[signum] = 0;
134
  fActionSet[signum] = false;
135
  return true;
136
}
137
 
138
//------------------------------------------+-----------------------------------
139
//! FIXME_docs
140
 
141
bool RtclSignalAction::ValidSignal(int signum, RerrMsg& emsg)
142
{
143
  if (signum > 0 && signum < 32) {
144
    switch (signum) {
145
    case SIGHUP:
146
    case SIGINT:
147
    case SIGTERM:
148
    case SIGUSR1:
149
    case SIGUSR2:
150
      return true;
151
    default:
152
      break;
153
    }
154
  }
155
  emsg.Init("RtclSignalAction::ValidSignal", "unsupported signal");
156
  return false;
157
}
158
 
159
//------------------------------------------+-----------------------------------
160
//! FIXME_docs
161
 
162
void RtclSignalAction::TclChannelHandler(int mask)
163
{
164
  char signum;
165
  Tcl_Read(fShuttleChn, (char*) &signum, sizeof(signum));
166
  // FIXME_code: handle return code
167
 
168
  Tcl_SetVar2Ex(fpInterp, "Rutil_signum", NULL, Tcl_NewIntObj((int)signum), 0);
169
  // FIXME_code: handle return code
170
 
171
  if ((Tcl_Obj*)fpScript[(int)signum]) {
172
    Tcl_EvalObjEx(fpInterp, fpScript[(int)signum], TCL_EVAL_GLOBAL);
173
    // FIXME_code: handle return code 
174
  }
175
 
176
  return;
177
}
178
 
179
//------------------------------------------+-----------------------------------
180
//! FIXME_docs
181
 
182
void RtclSignalAction::SignalHandler(int signum)
183
{
184
  if (fpObj && fpObj->fFdPipeWrite>0) {
185
    char signum_c = signum;
186
    int irc = ::write(fpObj->fFdPipeWrite, (void*) &signum_c, sizeof(signum_c));
187
    if (irc < 0)
188
      cerr << "RtclSignalAction::SignalHandler-E: write() failed, errno="
189
           << errno << endl;
190
  } else {
191
    cerr << "RtclSignalAction::SignalHandler-E: spurious call" << endl;
192
  }
193
  return;
194
}
195
 
196
//------------------------------------------+-----------------------------------
197
//! FIXME_docs
198
 
199
void RtclSignalAction::ThunkTclChannelHandler(ClientData cdata, int mask)
200
{
201
  if (fpObj) fpObj->TclChannelHandler(mask);
202
  return;
203
}
204
 
205
//------------------------------------------+-----------------------------------
206
//! FIXME_docs
207
 
208
void RtclSignalAction::ThunkTclExitProc(ClientData cdata)
209
{
210
  delete fpObj;
211
  fpObj = 0;
212
  return;
213
}
214
 
215
//------------------------------------------+-----------------------------------
216
//! constructor
217
 
218
RtclSignalAction::RtclSignalAction(Tcl_Interp* interp)
219
  : fpInterp(interp),
220
    fFdPipeRead(-1),
221
    fFdPipeWrite(-1),
222
    fShuttleChn(),
223
    fActionSet(),
224
    fpScript(),
225
    fOldAction()
226
{
227
  for (size_t i=0; i<32; i++) {
228
    fActionSet[i] = false;
229
    ::memset(&fOldAction[i], 0, sizeof(fOldAction[0]));
230
  }
231
 
232
  int pipefd[2];
233
  if (::pipe(pipefd) < 0)
234
    throw Rexception("RtclSignalAction::<ctor>", "pipe() failed: ", errno);
235
 
236
  fFdPipeRead  = pipefd[0];
237
  fFdPipeWrite = pipefd[1];
238
 
239
  fShuttleChn = Tcl_MakeFileChannel((ClientData)fFdPipeRead, TCL_READABLE);
240
 
241
  Tcl_SetChannelOption(NULL, fShuttleChn, "-buffersize", "64");
242
  Tcl_SetChannelOption(NULL, fShuttleChn, "-encoding", "binary");
243
  Tcl_SetChannelOption(NULL, fShuttleChn, "-translation", "binary");
244
 
245
  Tcl_CreateChannelHandler(fShuttleChn, TCL_READABLE,
246
                           (Tcl_FileProc*) ThunkTclChannelHandler,
247
                           (ClientData) this);
248
}
249
 
250
//------------------------------------------+-----------------------------------
251
//! Destructor
252
 
253
RtclSignalAction::~RtclSignalAction()
254
{
255
  for (size_t i=0; i<32; i++) {
256
    RerrMsg emsg;
257
    if (fActionSet[i]) ClearAction(i, emsg);
258
  }
259
}
260
 
261
 
262
} // end namespace Retro

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.