| 1 |
|
|---|
| 2 | /**************************************************************\
|
|---|
| 3 |
|
|---|
| 4 | Main program for the CTX G-APD HV supply, sends commands,
|
|---|
| 5 | reads and monitors status of the G-APD HV supply
|
|---|
| 6 |
|
|---|
| 7 | Name: hvcontrol.cpp
|
|---|
| 8 |
|
|---|
| 9 | Actions: Do global initialization, start threads
|
|---|
| 10 |
|
|---|
| 11 | Created by: Sebastian Commichau, November 2008
|
|---|
| 12 | commichau@phys.ethz.ch
|
|---|
| 13 | Updated by: Sabrina Stark, June 2008
|
|---|
| 14 | sabrina.stark@phys.ethz.ch
|
|---|
| 15 |
|
|---|
| 16 | \**************************************************************/
|
|---|
| 17 |
|
|---|
| 18 | #include <stdio.h>
|
|---|
| 19 | #include <stdlib.h>
|
|---|
| 20 | #include <string.h>
|
|---|
| 21 | #include <pthread.h>
|
|---|
| 22 | #include <signal.h>
|
|---|
| 23 |
|
|---|
| 24 | #include "ConsoleCommand.h"
|
|---|
| 25 | #include "CCCommand.h"
|
|---|
| 26 | #include "ProcessIO.h"
|
|---|
| 27 | #include "HVMonitor.h"
|
|---|
| 28 | #include "Types.h"
|
|---|
| 29 |
|
|---|
| 30 | #define Sleep(x) usleep(x*1000)
|
|---|
| 31 |
|
|---|
| 32 | #define DEFAULT_CONFIG "HV.conf" // Default configuration file
|
|---|
| 33 | #define LOCKFILE "/tmp/CTX_HV_LOCK"
|
|---|
| 34 |
|
|---|
| 35 | void CrashHandler(int Signal);
|
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 | int main(int argc, char *argv[]) {
|
|---|
| 39 |
|
|---|
| 40 |
|
|---|
| 41 | char config_file[] = DEFAULT_CONFIG, str[MAX_COM_SIZE];
|
|---|
| 42 |
|
|---|
| 43 | pthread_t thread_ConsoleCommand; // Read commands from console
|
|---|
| 44 | pthread_t thread_HVMonitor; // Reads continuously from HV board(s)
|
|---|
| 45 | pthread_t thread_CCCommand; // Thread listening to commands from Central Control
|
|---|
| 46 |
|
|---|
| 47 | int LockDescriptor;
|
|---|
| 48 |
|
|---|
| 49 | // Assure only one instance of the HV control program runs
|
|---|
| 50 | // The flag O_EXCL together with O_CREAT assure that the lock
|
|---|
| 51 | // file cannot be opened by another instance, i.e. there are no parallel write accesses
|
|---|
| 52 | /* if ((LockDescriptor = open(LOCKFILE,O_RDONLY|O_CREAT|O_EXCL)) == -1) {
|
|---|
| 53 | sprintf(str, "Could not create lock file %s", LOCKFILE);
|
|---|
| 54 | perror(str);
|
|---|
| 55 | exit(EXIT_FAILURE);
|
|---|
| 56 | }
|
|---|
| 57 | close(LockDescriptor);
|
|---|
| 58 | */
|
|---|
| 59 | if((LockDescriptor = 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 {
|
|---|
| 66 | sprintf(str, "Could not create lock file %s", LOCKFILE);
|
|---|
| 67 | perror(str);
|
|---|
| 68 | }
|
|---|
| 69 | exit(EXIT_FAILURE);
|
|---|
| 70 | }
|
|---|
| 71 | close(LockDescriptor);
|
|---|
| 72 | sprintf(str,"echo Created >%s; date >>%s; echo by $USER@$HOSTNAME>>%s",LOCKFILE,LOCKFILE,LOCKFILE);
|
|---|
| 73 | system(str);
|
|---|
| 74 |
|
|---|
| 75 |
|
|---|
| 76 | for (int i=1; i<argc; i++) {
|
|---|
| 77 | if (argv[i][0] == '-') {
|
|---|
| 78 | if (argv[i][1] == 'h') {
|
|---|
| 79 | printf("Usage: %s [-c <ConfigFile>] default file is \"%s\"\n", argv[0], config_file);
|
|---|
| 80 | exit(1);
|
|---|
| 81 | }
|
|---|
| 82 | if (argv[i][1] == 'c') {
|
|---|
| 83 | if (argc<i+2) {
|
|---|
| 84 | printf("Error: missing configuration file after -c option\n");
|
|---|
| 85 | exit(1);
|
|---|
| 86 | } else {
|
|---|
| 87 | sprintf(config_file, "%s", argv[i+1]);
|
|---|
| 88 | }
|
|---|
| 89 | }
|
|---|
| 90 | }
|
|---|
| 91 | }
|
|---|
| 92 |
|
|---|
| 93 | system("clear");
|
|---|
| 94 | printf("\n****************** HV Control %s built %s, %s by S. Commichau, updated by S. Stark ******************\n\n",HV_CONTROL_VERSION,__DATE__,__TIME__);
|
|---|
| 95 |
|
|---|
| 96 |
|
|---|
| 97 | // Construct main instance
|
|---|
| 98 | ProcessIO pio(config_file);
|
|---|
| 99 |
|
|---|
| 100 | // Install signal handler and set signal SIGUSR1 to interrupt blocking system calls
|
|---|
| 101 | signal(SIGUSR1, &SignalHandler);
|
|---|
| 102 | siginterrupt (SIGUSR1, true);
|
|---|
| 103 |
|
|---|
| 104 | // Install signals to assure that the lock file is deleted in case of a program crash
|
|---|
| 105 | signal(SIGQUIT, &CrashHandler);
|
|---|
| 106 | signal(SIGILL, &CrashHandler);
|
|---|
| 107 | signal(SIGABRT, &CrashHandler);
|
|---|
| 108 | signal(SIGFPE, &CrashHandler);
|
|---|
| 109 | signal(SIGSEGV, &CrashHandler);
|
|---|
| 110 | signal(SIGBUS, &CrashHandler);
|
|---|
| 111 | signal(SIGTERM, &CrashHandler);
|
|---|
| 112 | signal(SIGINT, &CrashHandler);
|
|---|
| 113 | signal(SIGHUP, &CrashHandler);
|
|---|
| 114 |
|
|---|
| 115 |
|
|---|
| 116 | // Create threads
|
|---|
| 117 | if ((pthread_create(&thread_ConsoleCommand, NULL, (void * (*)(void *)) ConsoleCommand,(void *) &pio)) != 0) {
|
|---|
| 118 | fprintf(stderr, "pthread_create failed with ConsoleCommand\n");
|
|---|
| 119 | exit(1);
|
|---|
| 120 | }
|
|---|
| 121 |
|
|---|
| 122 | if ((pthread_create(&thread_HVMonitor, NULL, (void * (*)(void *)) HVMonitor,(void *) &pio)) != 0) {
|
|---|
| 123 | fprintf(stderr, "pthread_create failed with HVMonitor\n");
|
|---|
| 124 | exit(1);
|
|---|
| 125 | }
|
|---|
| 126 |
|
|---|
| 127 | if ((pthread_create(&thread_CCCommand, NULL, (void * (*)(void *)) CCCommand,(void *) &pio)) != 0) {
|
|---|
| 128 | fprintf(stderr, "pthread_create failed with CCCommand\n");
|
|---|
| 129 | exit(1);
|
|---|
| 130 | }
|
|---|
| 131 |
|
|---|
| 132 | // Threads should be accessible for sending signals
|
|---|
| 133 | pio.status->HVMonitor = thread_HVMonitor;
|
|---|
| 134 | pio.status->SocketThread = thread_CCCommand;
|
|---|
| 135 |
|
|---|
| 136 | // Wait for threads to quit
|
|---|
| 137 | pthread_join(thread_CCCommand, NULL);
|
|---|
| 138 | pthread_join(thread_ConsoleCommand, NULL);
|
|---|
| 139 | pthread_join(thread_HVMonitor, NULL);
|
|---|
| 140 |
|
|---|
| 141 | // Remove lockfile
|
|---|
| 142 | if (remove(LOCKFILE)==-1) {
|
|---|
| 143 | sprintf(str, "Could not remove lock file %s", LOCKFILE);
|
|---|
| 144 | perror(str);
|
|---|
| 145 | exit(EXIT_FAILURE);
|
|---|
| 146 | }
|
|---|
| 147 |
|
|---|
| 148 | return 0;
|
|---|
| 149 | }
|
|---|
| 150 |
|
|---|
| 151 | // Remove lock file before running default signal code
|
|---|
| 152 | void CrashHandler(int Signal) {
|
|---|
| 153 | remove(LOCKFILE);
|
|---|
| 154 | printf("Caught signal number %d. Removing lockfile and performing standard signal action. Good luck.\n",Signal);
|
|---|
| 155 | signal(Signal, SIG_DFL);
|
|---|
| 156 | raise(Signal);
|
|---|
| 157 | }
|
|---|