source: drsdaq/drsdaq.cpp@ 23

Last change on this file since 23 was 22, checked in by ogrimm, 16 years ago
First commit of drsdaq program
File size: 8.1 KB
Line 
1/**************************************************************\
2
3 drsdaq.cpp
4
5 Main program for DRS CTX DAQ system. Global initialization,
6 starts threads for console input and socket interface.
7
8 Sebastian Commichau, Oliver Grimm
9
10\**************************************************************/
11
12#define DEFAULT_CONFIG "../config/DRSDAQ.conf" // Default configuration file
13#define LOCKFILE "/tmp/CT3_DAQ_LOCK"
14
15#include <stdio.h>
16#include <signal.h>
17#include <pthread.h>
18#include <sys/socket.h>
19#include <netdb.h>
20#include <arpa/inet.h>
21
22#include "DAQReadout.h"
23#include "HVFeedback.h"
24
25// Function prototypes
26void ConsoleCommand(DAQReadout *);
27void CCCommand(DAQReadout *);
28void SignalHandler(int);
29void CrashHandler(int);
30
31// ================
32// Main program
33// ================
34//
35// Several unlikely system call failures are handled via throwing an exception.
36
37int main(int argc, char *argv[]) {
38
39 char str[MAX_COM_SIZE];
40 pthread_t thread_ConsoleCommand, thread_CCCommand;
41 int LockDescriptor;
42
43 // Interpret command line (do before lockfile creation in case of exit())
44 if((argc==3 && strcmp(argv[1],"-c")!=0) || argc==2) {
45 printf("Usage: %s [-c <ConfigFile>] Default file is \"%s\"\n", argv[0], DEFAULT_CONFIG);
46 exit(EXIT_SUCCESS);
47 }
48
49 // Assure only one instance of program runs (lock creator written to log file)
50 if((LockDescriptor = open(LOCKFILE,O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1) {
51 if(errno==EEXIST) {
52 printf("Error: Lock file already existing\n");
53 sprintf(str,"paste %s -s -d ' '",LOCKFILE);
54 system(str);
55 }
56 else printf("Could not create lock file %s (%s)\n", LOCKFILE, strerror(errno));
57 exit(EXIT_FAILURE);
58 }
59 close(LockDescriptor);
60 sprintf(str,"echo Created >%s; date >>%s; echo by $USER@$HOSTNAME >>%s",LOCKFILE,LOCKFILE,LOCKFILE);
61 system(str);
62
63 system("clear");
64 printf("\n************* DRS readout built %s, %s\n\n",__DATE__,__TIME__);
65
66 // Set signal handlers
67 signal(SIGUSR1, &SignalHandler);
68 siginterrupt (SIGUSR1, true); // Set SIGUSR1 to interrupt (and not restart) blocking system calls
69 signal(SIGQUIT, &CrashHandler);
70 signal(SIGILL, &CrashHandler);
71 signal(SIGABRT, &CrashHandler);
72 signal(SIGFPE, &CrashHandler);
73 signal(SIGSEGV, &CrashHandler);
74 signal(SIGBUS, &CrashHandler);
75 signal(SIGTERM, &CrashHandler);
76 signal(SIGINT, &CrashHandler);
77
78 // Construct main instance
79 DAQReadout dreadout(argc==3 ? argv[2] : DEFAULT_CONFIG);
80
81 // Create threads and mutex for thread synchronization
82 if (pthread_mutex_init(&dreadout.control_mutex, NULL) != 0) {
83 perror("pthread_mutex_init failed");
84 throw;
85 }
86 if ((pthread_create(&thread_ConsoleCommand, NULL, (void * (*)(void *)) ConsoleCommand,(void *) &dreadout)) != 0) {
87 perror("pthread_create failed with console thread");
88 throw;
89 }
90 if ((pthread_create(&thread_CCCommand, NULL, (void * (*)(void *)) CCCommand,(void *) &dreadout)) != 0) {
91 perror("pthread_create failed with socket thread");
92 dreadout.SocketThread = NULL;
93 }
94 else dreadout.SocketThread = &thread_CCCommand; // Thread should be accessible for sending signals
95
96 // Wait for threads to quit
97 pthread_join(thread_ConsoleCommand, NULL);
98 if(dreadout.SocketThread != NULL) pthread_join(thread_CCCommand, NULL);
99
100 // Destruct mutex and main instance
101 pthread_mutex_destroy (&dreadout.control_mutex);
102 dreadout.~DAQReadout();
103
104 // Remove lockfile
105 if (remove(LOCKFILE)==-1) {
106 printf("Could not remove lock file %s (%s)\n", LOCKFILE, strerror(errno));
107 exit(EXIT_FAILURE);
108 }
109 exit(EXIT_SUCCESS);
110}
111
112
113/********************************************************************\
114
115 ConsoleCommand thread
116
117 Handle console input
118
119\********************************************************************/
120
121void ConsoleCommand(DAQReadout *m) {
122
123 char Command[MAX_COM_SIZE], Buf[MAX_COM_SIZE];
124 time_t Time;
125
126 while (!m->Exit) {
127 m->PrintMessage(""); // New prompt
128 if (fgets(Command, MAX_COM_SIZE, stdin)==NULL)
129 m->PrintMessage("Error reading command line input\n");
130
131 strftime(Buf,MAX_COM_SIZE,"%d/%m/%y %X", localtime(&(Time=time(NULL))));
132 m->PrintMessage(MsgToLog, "CONSOLE(%s)> %s",Buf, Command);
133
134 pthread_mutex_lock(&m->control_mutex);
135 m->CommandControl(Command, false);
136 pthread_mutex_unlock(&m->control_mutex);
137 }
138}
139
140
141
142/********************************************************************\
143
144 CCCommand thread
145
146 Listen to commands from socket (Central Control)
147
148 This thread will block execution in the accept() and read() socket function
149 while waiting for a connection or data. If the exit function is invoked through
150 keyboard command, these blocking functions are interrupted by raising the signal
151 SIGUSR1. Testing on errno=EINTR indicates this termination. The dummy signal
152 handler below is needed to prevent the standard thread termination occurring
153 when this signal is received.
154
155\********************************************************************/
156
157void CCCommand(DAQReadout *m) {
158
159 int ServerSocket,ConnectionSocket,ReadResult;
160 struct sockaddr_in SocketAddress, ClientAddress;
161 struct hostent *ClientName;
162 socklen_t SizeClientAddress=sizeof(ClientAddress);
163 char Command[MAX_COM_SIZE], Buf[MAX_COM_SIZE];
164 time_t Time;
165
166 // Set up server socket
167 if ((ServerSocket = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
168 m->PrintMessage("Could not open server socket, no remote connection possible (%s).\n", strerror(errno));
169 return;
170 }
171
172 SocketAddress.sin_family = PF_INET;
173 SocketAddress.sin_port = htons((unsigned short) m->fCCPort);
174 SocketAddress.sin_addr.s_addr = INADDR_ANY;
175 if (bind(ServerSocket, (struct sockaddr *) &SocketAddress, sizeof(SocketAddress)) == -1)
176 {
177 m->PrintMessage("Could not bind port to socket (%s)\n", strerror(errno));
178 close(ServerSocket);
179 return;
180 }
181 if (listen(ServerSocket, 0) == -1) {
182 m->PrintMessage("Could not set socket to listening (%s)\n", strerror(errno));
183 close(ServerSocket);
184 return;
185 }
186
187 // Looping to wait for incoming connection
188 while (!m->Exit) {
189 if ((ConnectionSocket = accept(ServerSocket, (struct sockaddr *) &ClientAddress, &SizeClientAddress)) == -1) {
190 if (errno!=EINTR) m->PrintMessage("Failed to accept incoming connection (%s)\n", strerror(errno));
191 close(ServerSocket);
192 return;
193 }
194
195 ClientName = gethostbyaddr((char *) &ClientAddress.sin_addr ,sizeof(struct sockaddr_in),AF_INET);
196 m->PrintMessage("Connected to client at %s (%s).\n", inet_ntoa(ClientAddress.sin_addr), ClientName!=NULL ? ClientName->h_name:"name unknown");
197 m->Socket = ConnectionSocket;
198
199 while (!m->Exit) { // Looping as long as client exists
200 memset(Command,0,sizeof(Command));
201 ReadResult = read(ConnectionSocket, Command, MAX_COM_SIZE);
202 if (ReadResult==0) break; // Client no exisiting anymore
203 if (ReadResult==-1) {
204 if (errno!=EINTR) m->PrintMessage("Error read from socket (%s)\n", strerror(errno));
205 break;
206 }
207
208 strftime(Buf,MAX_COM_SIZE,"%d/%m/%y %X", localtime(&(Time=time(NULL))));
209 m->PrintMessage(MsgToLog,"SOCKET(%s)> %s%s",Buf, Command, Command[strlen(Command)-1]=='\n' ? "":"\n");
210 m->PrintMessage(MsgToConsole,"SOCKET> %s%s",Command, Command[strlen(Command)-1]=='\n' ? "":"\n");
211
212 pthread_mutex_lock(&m->control_mutex);
213 m->CommandControl(Command, true); // Process CC command
214 pthread_mutex_unlock(&m->control_mutex);
215 m->PrintMessage(""); // New prompt
216 }
217 m->Socket = -1;
218 m->PrintMessage("Disconnected from client.\n");
219 close(ConnectionSocket);
220 }
221 close(ServerSocket);
222 m->PrintMessage("Server socket closed.\n");
223}
224
225
226/********************************************************************\
227
228 Signal handlers
229
230\********************************************************************/
231
232// Remove lock file before running default signal code
233void CrashHandler(int Signal) {
234 remove(LOCKFILE);
235 printf("Caught signal number %d. Removing lockfile and performing standard signal action. Good luck.\n",Signal);
236 signal(Signal, SIG_DFL);
237 raise(Signal);
238}
239
240// Dummy signal handler to return from blocking syscalls
241void SignalHandler(int Signal) {
242 return;
243}
Note: See TracBrowser for help on using the repository browser.