Changeset 10153


Ignore:
Timestamp:
02/11/11 10:03:46 (14 years ago)
Author:
ogrimm
Message:
New command 'crate', changed signalling of program exit
Location:
fact/BIASctrl
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • fact/BIASctrl/BIASctrl.cc

    r10070 r10153  
    11/**************************************************************\
    22
    3   Control program for the fACT G-APD bias supply
     3  Control program for the FACT G-APD bias supply
    44
    5   Adapted from previous version 'hvcontrol'.
    6  
    7   Oliver Grimm, August 2010
     5  Oliver Grimm
    86 
    97\**************************************************************/
     
    1614#include <readline/history.h>
    1715
    18 #define LOCKFILE "/tmp/CTX_HV_LOCK"
    1916const char READLINE_HIST_FILE[] = "/tmp/.history.BIASctrl";
    2017
    21 //
    22 // Remove lock file before running default signal code
    23 //
    24 void CrashHandler(int Signal) {
    25 
    26   remove(LOCKFILE);
    27   printf("Caught signal number %d. Removing lockfile and performing standard signal action. Good luck.\n",Signal);
    28   signal(Signal, SIG_DFL);
    29   raise(Signal);
    30 }
    31 
    32 //
    33 // Dummy handler to return from blocking syscalls
    34 //
    35 void DummyHandler(int) {};
    36 
    37 //
    38 // This function will be implicitly called by exit()
    39 //
    40 void ExitFunction() {
    41 
    42   if (remove(LOCKFILE) == -1) {
    43     printf("Could not remove lock file %s (%s)\n", LOCKFILE, strerror(errno));
    44   }
    45 }
    46 
    47 //
    4818// Main program
    49 //
    5019int main() {
    5120
    52   char str[MAX_COM_SIZE], *Command;
    53   int Lock;
     21  char *Command;
    5422  std::string LastHist;
    5523
    56   // Assure only one instance runs
    57   // O_EXCL with O_CREAT assure that the lock file cannot be
    58   // opened by another instance, i.e. there are no parallel write accesses
    59   if((Lock = open(LOCKFILE,O_WRONLY|O_CREAT|O_EXCL,S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1) {
    60     if(errno==EEXIST) {
    61       printf("Error: Lock file already existing\n");
    62       sprintf(str, "paste %s -s -d ' '", LOCKFILE);
    63       system(str);
    64     }
    65     else printf("Could not create lock file %s (%s)\n", LOCKFILE, strerror(errno));
    66     exit(EXIT_FAILURE);
    67   }
    68   close(Lock);
    69   sprintf(str,"echo Created >%s; date >>%s; echo by $USER@$HOSTNAME>>%s", LOCKFILE, LOCKFILE, LOCKFILE);
    70   system(str);
    71  
     24  // Uses getc() for readline library (allows interruption by signal) and load history buffer
     25  rl_getc_function = getc;
     26  read_history(READLINE_HIST_FILE);
     27
     28  // Set signal SIGTERM to interrupt blocking system calls
     29  siginterrupt(SIGTERM, true);
     30
    7231  system("clear");                   
    73   printf("\n*** Bias control (compiled %s, %s) ***\n\n", __DATE__, __TIME__);
    74  
    75   // Install signal handler and set signal SIGUSR1 to interrupt blocking system calls
    76   signal(SIGUSR1, &DummyHandler);
    77   siginterrupt (SIGUSR1, true);
    78 
    79   // Assure lock file is deleted in case of a program crash or call to exit()
    80   signal(SIGILL, &CrashHandler);
    81   signal(SIGABRT, &CrashHandler);
    82   signal(SIGFPE, &CrashHandler);
    83   signal(SIGSEGV, &CrashHandler);
    84   signal(SIGBUS, &CrashHandler);
    85   atexit(&ExitFunction);
    86  
     32  printf("\n*** BIASctrl (compiled %s, %s) ***\n\n", __DATE__, __TIME__);
     33   
    8734  // Construct main instance
    8835  static User M;
    8936 
    90   // These signals were set during construction of EvidenceServer
    91   signal(SIGQUIT, &CrashHandler);  // CTRL-Backspace
    92   signal(SIGINT, &CrashHandler);   // CTRL-C
    93   signal(SIGHUP, &CrashHandler);   // Terminal closed
    94   signal(SIGTERM, &CrashHandler);
    95 
    96   // Load history buffer
    97   read_history(READLINE_HIST_FILE);
    98 
    9937  // Handle command-line input
    10038  while (!M.ExitRequest) {       
  • fact/BIASctrl/Crate.cc

    r10118 r10153  
    134134        FD_ZERO(&SelectDescriptor);   FD_SET(fDescriptor, &SelectDescriptor);
    135135        if (select(fDescriptor+1, &SelectDescriptor, NULL, NULL, &WaitTime)==-1) {
     136          if (errno = EINTR) goto ExitCommunicate;  // in case program is exiting
    136137      m->Message(m->FATAL, "Error with select() (%s)", strerror(errno));
    137138        }
  • fact/BIASctrl/History.txt

    r10107 r10153  
    776/1/2011        RampVoltages() had infinite loop if crate communication stopped
    8819/1/2011       'hv' command crashed when no bias board was present
     928/1/2011       Replaced 'hv' by 'channel' and 'pixel' commands (with new pixel
     10                        names, the name is a number itself)
     1111/2/2011       Removed Lockfile (DIM will prevent starting two instances)
     12                        Added 'crate' command. Changed signaling of program exit.
  • fact/BIASctrl/User.cc

    r10119 r10153  
    1515                                                                const char *Help;
    1616  } CommandList[] =
    17    {{"synch", &User::cmd_synch, 0, "", "Synchronize board"},
    18     {"pixel", &User::cmd_hv, 2, "<pixel id> <v>", "Change bias of pixel"},
    19         {"channel", &User::cmd_hv, 2, "<channel|all> <v>", "Change bias of (all) channels of active boards"},
    20     {"gs", &User::cmd_gs, 1, "[crate] <volt>", "Global voltage set"},
     17   {{"pixel", &User::cmd_hv, 2, "<pixel id> <v>", "Change bias of pixel"},
     18        {"channel", &User::cmd_hv, 2, "<channel range> <v>", "Change bias of (all) channels of active crate"},
     19    {"gs", &User::cmd_gs, 1, "[crate] <volt>", "Global voltage set active crate"},
     20        {"reset", &User::cmd_reset, 0, "", "Reset active crate"},
     21        {"synch", &User::cmd_synch, 0, "", "Synchronize active crate"}, {"crate", &User::cmd_crate, 1, "<number>", "Select active crate"},
    2122        {"status", &User::cmd_status, 0, "[dac|current]", "Show status information (DAC values if requested)"},
    22         {"mode", &User::cmd_mode, 1, "<static|dynamic>", "Set voltage stabilization mode"},
     23        {"mode", &User::cmd_mode, 1, "<static|dynamic>", "Set voltage stabilization mode (experimental)"},
    2324        {"load", &User::cmd_load, 1, "<file>", "Load and set bias settings from file"},
    2425        {"save", &User::cmd_save, 1, "<file>", "Save current bias settings to file"},
    2526        {"rate", &User::cmd_rate, 1, "<rate>", "Set refresh rate in Hz"},
    2627        {"timeout", &User::cmd_timeout, 1, "<time>", "Set timeout to return from read in seconds"},
    27         {"reset", &User::cmd_reset, 1, "<crates>", "Reset crates"},
    2828        {"help", &User::cmd_help, 0, "", "Print help"},
    2929        {"exit", &User::cmd_exit, 0, "", "Exit program"}};
     
    3434//
    3535User::User(): EvidenceServer(SERVER_NAME) {
     36
     37  MainThread = pthread_self();
    3638
    3739  // DIM console service used in PrintMessage()
     
    6365  }
    6466
     67  // Set active crate
     68  if (!Boards.empty()) ActiveCrate = 0;
     69  else ActiveCrate = -1;
     70
    6571  // Create PixelMap instance (map from config server)
    6672  DimRpcInfo RPC((char *) "ConfigRequest", (char *) "");
     
    7783}
    7884
    79 
    8085//
    8186// Destructor
     
    8489
    8590  // Wait for thread to quit
    86   if (pthread_join(Thread, NULL) != 0) {
    87     PrintMessage("pthread_join() failed");
    88   }
     91  if (pthread_cancel(Thread) != 0) Message(ERROR, "pthread_cancel() failed in ()");
     92  if (pthread_join(Thread, NULL) != 0) Message(ERROR, "pthread_join() failed in ()");
    8993
    9094  // Delete all crates
     
    144148 
    145149  PrintMessage(".<command>                  Execute shell command\n\n"
    146         "Items in <> are mandatory, in [] optional, | indicates mutual exclusive or.\n");
     150        "Items in <> are mandatory, in [] optional, | indicates mutual exclusive or.\n"
     151    "Channel ranges can be 'all', a single number or in the form 'a-b'.\n");
    147152}
    148153
     
    152157void User::cmd_synch() {
    153158
    154   for (unsigned int i=0; i<Crates.size(); i++) {
    155         if (Crates[i]->Synch()) PrintMessage("Synchronized crate %d\n", i);
    156         else PrintMessage("Failed to synchronize crate %d\n", i);
    157   }
     159  if (ActiveCrate == -1) return; 
     160
     161  if (Crates[ActiveCrate]->Synch()) PrintMessage("Synchronized crate %d\n", ActiveCrate);
     162  else PrintMessage("Failed to synchronize crate %d\n", ActiveCrate);
     163}
     164
     165//
     166// Select active crate
     167//
     168void User::cmd_crate() {
     169
     170  int Crate;
     171
     172  if (!ConvertToInt(Parameter[1], &Crate)) {
     173     PrintMessage("Error: Wrong number format\n");
     174     return;   
     175  }
     176
     177  // Check limits
     178  if (Crate<0 || Crate>=(int) Crates.size()) {
     179    PrintMessage("Crate number %d not existing\n", Crate);
     180    return;
     181  }
     182
     183  ActiveCrate = Crate;
    158184}
    159185
     
    183209        // Channel identification
    184210        else {
    185       vector<string> T = Tokenize(Parameter[n], "/");
    186           Crt.Min = 0;
    187           Crt.Max = Crates.size()-1;
     211          if (ActiveCrate == -1) continue;
     212          else  Crt.Min = Crt.Max = ActiveCrate;
     213
    188214          Chan.Min = 0;
    189           Chan.Max = MAX_NUM_BOARDS*NUM_CHANNELS-1;
    190          
    191           if (T.size() == 2) {
    192                 if(!ConvertToRange(T[0], Crt) || !ConvertToRange(T[1], Chan)) {
    193                   PrintMessage("Numeric conversion or out-of-range error for parameter %d, skipping channel\n", n);
    194                   continue;
    195                 }
    196           }
    197           else {
    198                 Crt.Min = Crt.Max = 0;
    199                 if (!ConvertToRange(T[0], Chan)) {
    200                   PrintMessage("Numeric conversion or out-of-range error for parameter %d, skipping channel\n", n);
    201                   continue;
    202                 }
     215          Chan.Max = MAX_NUM_BOARDS*NUM_CHANNELS-1;       
     216
     217          if (!ConvertToRange(Parameter[n], Chan)) {
     218                PrintMessage("Numeric conversion or out-of-range error for parameter %d, skipping channel\n", n);
     219                continue;
    203220          }
    204221        }
     
    246263  char Buffer[MAX_COM_SIZE];
    247264  int Errors = 0, Channel;
    248   unsigned int NBoards = 0;
    249265  double Value;
    250266  FILE *File;
     
    261277    for (unsigned int Crate=0; Crate<Crates.size(); Crate++) if (Match(Crates[Crate]->Name, Buffer)) {
    262278
    263           PrintMessage("Found bias settings for board %s (#%d)\n\r", Crates[Crate]->Name, Crate);
     279          if ((int) Crate != ActiveCrate) continue;
     280          PrintMessage("Found bias settings for crate %s (#%d)\n\r", Crates[Crate]->Name, Crate);
    264281
    265282          Voltages.clear();
     
    280297          }
    281298          else PrintMessage("\nFinished updating board\n");
    282       NBoards++;
    283299    } // Loop over boards
    284300  } // while()
    285301           
    286   if (NBoards != Crates.size()) PrintMessage("Warning: Could not load bias settings for all connected crates\n");
    287   else if (Errors == 0) PrintMessage("Success: Read bias settings for all connected crates\n");
    288 
    289302  if (Errors != 0) PrintMessage("Warning: %d error(s) occurred\n", Errors);
    290 
    291303  if (fclose(File) != 0) PrintMessage("Error: Could not close file '%s'\n", Parameter[1].c_str());
    292304}
     
    319331void User::cmd_reset() {
    320332
    321   struct Range R = {0, Crates.size()-1};
    322 
    323   // Check ranges 
    324   if(!ConvertToRange(Parameter[1], R)) {
    325         PrintMessage("Error, crate number out of range\n");
     333  if (ActiveCrate == -1) return; 
     334 
     335  if (Crates[ActiveCrate]->SystemReset() == 1) PrintMessage("System reset of crate %d\n", ActiveCrate);
     336  else PrintMessage("Error: Could not reset crate %d\n", ActiveCrate);
     337
     338}
     339
     340//
     341// Read channel
     342//
     343void User::cmd_gs() {
     344
     345  double Voltage;
     346
     347  if (ActiveCrate == -1) return; 
     348
     349  if (!ConvertToDouble(Parameter[1], &Voltage)) {
     350    PrintMessage("Error: Wrong number format\n");
    326351        return;
    327352  }
    328353 
    329   for (int i=R.Min; i<=R.Max; i++) {
    330         if (Crates[i]->SystemReset() == 1) PrintMessage("System reset of crate %s (#%d)\n", Crates[i]->Name, i);
    331         else PrintMessage("Error: Could not reset board %s (#%d)\n", Crates[i]->Name, i);
    332   }
    333 }
    334 
    335 //
    336 // Read channel
    337 //
    338 void User::cmd_gs() {
    339 
    340   double Voltage;
    341 
    342   if (!ConvertToDouble(Parameter[1], &Voltage)) return;
    343 
    344   for (unsigned int i=0; i<Crates.size(); i++) {
    345         if (Crates[i]->GlobalSet(Voltage) != 1) {
    346           PrintMessage("Error: Could not global set crate %d\n", i);
    347         }
    348   }   
     354  if (Crates[ActiveCrate]->GlobalSet(Voltage) != 1) {
     355        PrintMessage("Error: Could not global set crate %d\n", ActiveCrate);
     356  } 
    349357}
    350358
     
    396404
    397405  PrintMessage(" Number of crates:  %d\n", Crates.size());
     406  PrintMessage(" Active crate:     %d\n", ActiveCrate); 
    398407  PrintMessage(" Refresh rate:      %.2f Hz\n", fStatusRefreshRate);
    399408  PrintMessage(" Time out:          %.2f s\n\n", fTimeOut);
     
    437446   
    438447//
    439 // Exit program
     448// Exit program (Signal makes readline return and sets ExitRequest)
    440449//
    441450void User::cmd_exit() {
    442451
    443   ExitRequest = true;
    444   pthread_kill(Thread, SIGUSR1);  // Make tjread return from usleep()
     452  pthread_kill(MainThread, SIGTERM);
    445453}
    446454 
     
    512520
    513521  static bool Warned = false;
     522  int Ret;
    514523
    515524  while (!ExitRequest) {
     525
     526        // Wait (this is the only allowed cancelation point)
     527        if ((Ret=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) != 0) {
     528          Message(FATAL, "pthread_setcancelstate() failed (%s)", strerror(Ret));
     529        }
     530        if (usleep((unsigned long) floor(1000000./fStatusRefreshRate)) == -1) {
     531          Message(FATAL, "usleep() failed (%s)", strerror(errno));
     532        }
     533        if ((Ret=pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL)) != 0) {
     534          Message(FATAL, "pthread_setcancelstate() failed (%s)", strerror(Ret));
     535        }
     536
     537        // Check all crates
    516538        for (unsigned int i=0; i<Crates.size(); i++) {
    517539      if (Crates[i]->ErrorCount > MAX_ERR_COUNT) {
    518540        if (!Warned) {
    519541          Warned = true;
    520           Message(WARN, "Warning: Crate %d has many read/write errors, further error reporting disabled", i);
     542          Message(WARN, "Crate %d has many read/write errors, further error reporting disabled", i);
    521543        }
    522544        continue;
     
    553575          if (Mode == mode_dynamic) Crates[i]->AdaptVoltages();
    554576        } // for
    555 
    556         // Wait
    557         usleep((unsigned long) floor(1000000./fStatusRefreshRate));
    558577  } // while
    559578}
  • fact/BIASctrl/User.h

    r10118 r10153  
    3030        DimService *ConsoleOut;
    3131        char *ConsoleText;
    32         pthread_t Thread;
     32        pthread_t MainThread, Thread;
    3333        std::vector<std::string> Parameter;
    3434        RunMode Mode;
     
    5252        float fStatusRefreshRate;
    5353        double fMaxDiff;
     54        int ActiveCrate;
    5455
    5556        User();
     
    6768        void cmd_timeout();     void cmd_reset();
    6869        void cmd_help();        void cmd_mode();
     70        void cmd_crate();
    6971};
    7072
Note: See TracChangeset for help on using the changeset viewer.