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

Subversion Repositories w11

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

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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