Changeset 255 for Evidence


Ignore:
Timestamp:
07/21/10 15:07:37 (14 years ago)
Author:
ogrimm
Message:
Added special handling of code 0 in exitHandler(), fixed recursion bug in Lock()/Unlock() by not calling Message()
Location:
Evidence
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • Evidence/Alarm.cc

    r253 r255  
    124124  // Identify status service
    125125  for (int i=0; i<List.size(); i++) if (getInfo() == List[i].Subscription) {
    126         // Update level: unavailable or current severity of status
     126        // Update level: unavailable or current severity of status (safely extracted)
    127127        if (!ServiceOK(getInfo())) List[i].Level = 4;
    128         else if (getInfo()->getInt() > List[i].Level) List[i].Level = getInfo()->getInt();
     128        else {
     129          int Severity = atoi(ToString(getInfo()->getFormat(), getInfo()->getData(), getInfo()->getSize()).c_str());
     130          if (Severity > List[i].Level) List[i].Level = Severity;
     131        }
    129132  }
    130133
     
    140143  if (getCommand() != Command || Server.empty()) return;
    141144 
    142   // Reset alarm level and publish/log action
     145  // Reset alarm level, publish/log action and reset server message severity
    143146  for (int i=0; i<List.size(); i++) if (List[i].Server == Server) {
    144147    Message(INFO, "Alarm level of server %s reset by %s (ID %d)", Server.c_str(), getClientName(), getClientId());
    145148        List[i].Level = 0;
    146149        List[i].WarnedLevel = 0;
     150        if (Server != "DIS_DNS") sendCommandNB((Server+"/EXIT").c_str(), (int) 0);
    147151  }
    148152 
     
    155159
    156160  ostringstream Buf;
    157   int Alarm, Ret; 
     161  int Alarm = 0, Ret; 
    158162
    159163  Lock();
     
    223227      }
    224228          if (!Exist) Alarm.List[i].Level = 4;
    225           else if (Alarm.List[i].Level = -1) Alarm.List[i].Level = 0;
     229          else if (Alarm.List[i].Level == -1) Alarm.List[i].Level = 0;
    226230    }
    227231   
  • Evidence/Doc/Evidence.tex

    • Property svn:keywords set to Rev
    r253 r255  
    3939\maketitle
    4040
    41 This report describes the design and basic functionality of the \E control system. This essentially is a C++ class and a set of programs running on Linux for controlling small scale experiments. It is based on CERN's DIM library for interprocess communication over TCP/IP connections.
     41This report describes the design and basic functionality of the \E control system. This essentially is a C++ class and a set of programs running on Linux for controlling small scale experiments. It is based on CERN's DIM library for interprocess communication over TCP/IP connections. \lstinline{$Rev$}
    4242
    4343\tableofcontents
     
    130130\item Provides a method for configuration requests. If the configuration data is not available, the application terminates with a  message of FATAL severity unless default data is given.
    131131\item Provides a method for safely translating DIM service data into text.
    132 \item Implements the virtual DIM methods \lstinline{exitHandler()} and \lstinline{errorHandler()}. The exit handler can be called through a standard DIM command and will, upon first invocation, just set the flag \lstinline{ExitRequest} which then should be handled by the application. Upon second invocation, it will call \lstinline{exit()}. The error handler will issue a message with ERROR severity.The user application can override these handlers.
     132\item Implements the virtual DIM methods \lstinline{exitHandler()}. It can be called through a standard DIM command \lstinline{SvrName/EXIT}, taking a single integer as argument. Upon first invocation, the handler just sets the flag \lstinline{ExitRequest} which should be handled by the application. Upon second invocation, it will call \lstinline{exit()}. A special functionality is given to the argument value 0: it instructs the server to reset its message severity to INFO, without exiting. This is used by the \lstinline{Alarm} server if it receives a command to reset an alarm level, but is also available to the user. The user application can override this handler.
     133\item Implements the virtual DIM methods \lstinline{errorHandler()}. The error handler will issue a message with ERROR severity that contains the DIM error code. The user application can override this handler.
    133134\item Installs signal handler for SIGQUIT (ctrl-backspace), SIGTERM, SIGINT (ctrl-c), and SIGHUP (terminal closed). The signal handler sets first \lstinline{ExitRequest}, and on second invocation calls \lstinline{exit()}. After instantiating the class, the programmer may override the handlers.
    134135\item Catches un-handled C++ exceptions and extracts as much information from the exception as possible.\footnote{This termination handler is taken directly from the code of the \lstinline{g++} compiler and is thus compiler specific.} That information is also published as a message.
     
    140141\label{EvidenceServer-Methods}
    141142
    142 The \lstinline{public} part of the header file \lstinline{Evidence.h} is as follows. The namespace designation \lstinline{std} has been left out for clarity in this listing. 
     143The \lstinline{public} part of the header file \lstinline{Evidence.h} is as follows. The namespace designation \lstinline{std} has been left out for clarity in this listing.
    143144
    144145\begin{lstlisting}[numbers=left,numberstyle=\tiny,stepnumber=2,numbersep=5pt]
     
    180181\underline{\lstinline{ActivateSignal()}} is used to define a signal that should be emitted to the main thread in case the configuration file changes. See Sect.\,\ref{ConfigHandling} for details. No signal will be emitted if not set by this routine.
    181182
    182 The methods \underline{\lstinline{Lock()}} and \underline{\lstinline{Unlock()}} work on an internal mutex.\footnote{Its type is \lstinline{PTHREAD_MUTEX_ERRORCHECK}. In case an already locked mutex is re-locked, the corresponding system call will therefore return a error and thus avoid dead-locking.} They are used by \lstinline{GetConfig()} but are also available for the user application to serialize access from multiple threads. If a signal is set by \lstinline{ActivateSignal()}, it is masked before locking and unmasked after unlocking.
     183The methods \underline{\lstinline{Lock()}} and \underline{\lstinline{Unlock()}} work on an internal mutex.\footnote{Its type is \lstinline{PTHREAD_MUTEX_ERRORCHECK}. In case an already locked mutex is re-locked, the corresponding system call will therefore return a error and thus avoid dead-locking. Error messages from \lstinline{Lock()} and \lstinline{Unlock()} are written to the console and to the log file. They are not published using \lstinline{Message()} since this method itself uses locking and calling it would result in an infinite recursion.} They are used by \lstinline{GetConfig()} but are also available for the user application to serialize access from multiple threads. If a signal is set by \lstinline{ActivateSignal()}, it is masked before locking and unmasked after unlocking. Calling functions in the locked state should be avoided as it might result in re-locking.
    183184
    184185The static method \underline{\lstinline{ToString()}} translates the contents of a DIM service safely into a string that is returned. As no consistency between a service format and the contained data is guaranteed by DIM, precautions are necessary to avoid buffer overruns. The method currently handles the standardized message format \lstinline{"I:1;C"}, arrays of numbers and strings. All other formats are translated into a hex representation. The arguments are the DIM service format, a pointer to the service data and the data size in bytes. It is thread safe as it uses only the arguments and dynamically allocated storage.
  • Evidence/Evidence.cc

    r253 r255  
    122122          // Return current value
    123123          Result = List[Item].Value;
    124           This->Unlock();
    125124        }
     125        This->Unlock();
    126126  }
    127127
     
    200200void EvidenceServer::exitHandler(int Code) {
    201201
    202   Message(INFO, "Exit handler called (DIM exit code %d)", Code);
    203   exit(EXIT_SUCCESS);
     202  if (Code == 0) Message(INFO, "Message cleared by %s (ID %d)", getClientName(), getClientId());
     203  else {
     204        Message(INFO, "Exit handler called (DIM exit code %d)", Code);
     205        exit(EXIT_SUCCESS);
     206  }
    204207}
    205208
     
    241244  }
    242245
    243   // Terminate if severity if FATAL 
    244   if (Severity == FATAL) exit(EXIT_FAILURE);
    245 
    246246  // Delete old message
    247   // Note that Lock()/Unlock() might fail with a FATAL message. To avoid an infinite loop,
    248   // check for FATAL severity is done before here.
    249247  Lock();
    250248  delete[] MessageData;
    251249  MessageData = NewMsg;
    252250  Unlock(); 
    253 }
    254 
    255 
    256 // Set to central logging server with non-blocking command (may be used in DIM handler)
     251
     252  // Terminate if severity if FATAL 
     253  if (Severity == FATAL) exit(EXIT_FAILURE);
     254}
     255
     256
     257// Send to central logging server with non-blocking command
    257258void EvidenceServer::SendToLog(const char *Format, ...) {
    258259
     260  static char ErrorString[] = "vasprintf() failed in SendToLog()";
    259261  char *Buffer;
    260262  int Ret;
     
    271273        free (Buffer);
    272274  }
    273   else Message(ERROR, "Could not create logging text in SendToLog(), vasprintf() failed");
     275  else DimClient::sendCommandNB("DColl/Log", ErrorString);
    274276}
    275277
     
    300302
    301303
    302 // Locking and unlocking for list access
    303 // Signal blocked before locking to avoid dead-lock by calling GetConfig() from ConfigChanged().
     304// Locking and unlocking functions.
     305// Signal blocked before locking (pthread_mutex_lock() not asynch-signal safe).
     306// Message() is not used to avoid infinite recursion
    304307void EvidenceServer::Lock() {
    305308
     
    312315        Ret += abs(pthread_sigmask(SIG_BLOCK, &Set, NULL));
    313316
    314         if (Ret != 0) Message(FATAL, "Signal masking failed in Lock()");
     317        if (Ret != 0) {
     318          printf("Signal masking failed in Lock()");
     319          SendToLog("Signal masking failed in Lock()");
     320          exit(EXIT_FAILURE);
     321        }
    315322  }
    316323
    317324  if ((Ret = pthread_mutex_lock(&Mutex)) != 0) {
    318         Message(FATAL, "pthread_mutex_lock() failed in Lock() (%s)", strerror(Ret));
     325        printf("pthread_mutex_lock() failed in Lock() (%s)", strerror(Ret));
     326        SendToLog("pthread_mutex_lock() failed in Lock() (%s)", strerror(Ret));
     327        exit(EXIT_FAILURE);
    319328  }
    320329}
     
    326335
    327336  if ((Ret = pthread_mutex_unlock(&Mutex)) != 0) {
    328         Message(FATAL, "pthread_mutex_unlock() failed in Unlock() (%s)", strerror(Ret));
     337        printf("pthread_mutex_unlock() failed in Unlock() (%s)", strerror(Ret));
     338        SendToLog("pthread_mutex_unlock() failed in Unlock() (%s)", strerror(Ret));
     339        exit(EXIT_FAILURE);
    329340  }
    330341 
     
    334345        Ret += abs(pthread_sigmask(SIG_UNBLOCK, &Set, NULL));
    335346
    336         if (Ret != 0) Message(FATAL, "Signal unmasking failed in Unlock()");
     347        if (Ret != 0) {
     348          printf("Signal unmasking failed in Unlock()");
     349          SendToLog("Signal unmasking failed in Unlock()");
     350          exit(EXIT_FAILURE);
     351        }
    337352  }
    338353}
  • Evidence/readme.txt

    r253 r255  
    1 Short description of Evidence control system
    21
    32This directory contains the backbone of the control system. See directory Doc for documentation.
     
    4443                        second-last message will not be freed correctly if severity is FATAL). Added
    4544                        History server configuration parameters to adjust buffer size.
    46 
     4520/7/2010       SendToLog() does not call Message() in case of error, but writes error message to log.
     4621/7/2010       Lock()/Unlock() do not report errors via Message(), but print to console and use
     47                        SendToLog(). That avoids a recursion problem since Message() also uses locking.
     48                        The general exitHandler() will react in a special way to code 0: it will reset
     49                        the message severity. This feature is used by Alarm if it receives a command to
     50                        reset an alarm level.
Note: See TracChangeset for help on using the changeset viewer.