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

Subversion Repositories w11

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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