source: drsdaq/drsdaq.cpp@ 44

Last change on this file since 44 was 44, checked in by ogrimm, 15 years ago
Raw data format streamlined, revision tracking in run header
File size: 8.4 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 (revision %s) *** \n\n",__DATE__, __TIME__, REVISION);
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 signal(SIGHUP, &CrashHandler);
78
79 // Construct main instance
80 DAQReadout dreadout(argc==3 ? argv[2] : DEFAULT_CONFIG);
81
82 // Create threads and mutex for thread synchronization
83 if (pthread_mutex_init(&dreadout.control_mutex, NULL) != 0) {
84 perror("pthread_mutex_init failed");
85 throw;
86 }
87 if ((pthread_create(&thread_ConsoleCommand, NULL, (void * (*)(void *)) ConsoleCommand,(void *) &dreadout)) != 0) {
88 perror("pthread_create failed with console thread");
89 throw;
90 }
91 if ((pthread_create(&thread_CCCommand, NULL, (void * (*)(void *)) CCCommand,(void *) &dreadout)) != 0) {
92 perror("pthread_create failed with socket thread");
93 dreadout.SocketThread = NULL;
94 }
95 else dreadout.SocketThread = &thread_CCCommand; // Thread should be accessible for sending signals
96
97 // Wait for threads to quit
98 pthread_join(thread_ConsoleCommand, NULL);
99 if(dreadout.SocketThread != NULL) pthread_join(thread_CCCommand, NULL);
100
101 // Destruct mutex and main instance
102 pthread_mutex_destroy (&dreadout.control_mutex);
103 dreadout.~DAQReadout();
104
105 // Remove lockfile
106 if (remove(LOCKFILE)==-1) {
107 printf("Could not remove lock file %s (%s)\n", LOCKFILE, strerror(errno));
108 exit(EXIT_FAILURE);
109 }
110 exit(EXIT_SUCCESS);
111}
112
113
114/********************************************************************\
115
116 ConsoleCommand thread
117
118 Handle console input
119
120\********************************************************************/
121
122void ConsoleCommand(DAQReadout *m) {
123
124 char Command[MAX_COM_SIZE], Buf[MAX_COM_SIZE];
125 time_t Time;
126
127 while (!m->Exit) {
128 m->PrintMessage(""); // New prompt
129 if (fgets(Command, MAX_COM_SIZE, stdin)==NULL)
130 m->PrintMessage("Error reading command line input\n");
131
132 strftime(Buf,MAX_COM_SIZE,"%d/%m/%y %X", localtime(&(Time=time(NULL))));
133 m->PrintMessage(MsgToLog, "CONSOLE(%s)> %s",Buf, Command);
134
135 pthread_mutex_lock(&m->control_mutex);
136 m->CommandControl(Command, false);
137 pthread_mutex_unlock(&m->control_mutex);
138 }
139}
140
141
142
143/********************************************************************\
144
145 CCCommand thread
146
147 Listen to commands from socket (Central Control)
148
149 This thread will block execution in the accept() and read() socket function
150 while waiting for a connection or data. If the exit function is invoked through
151 keyboard command, these blocking functions are interrupted by raising the signal
152 SIGUSR1. Testing on errno=EINTR indicates this termination. The dummy signal
153 handler below is needed to prevent the standard thread termination occurring
154 when this signal is received.
155
156\********************************************************************/
157
158void CCCommand(DAQReadout *m) {
159
160 int ServerSocket,ConnectionSocket,ReadResult;
161 struct sockaddr_in SocketAddress, ClientAddress;
162 struct hostent *ClientName;
163 socklen_t SizeClientAddress=sizeof(ClientAddress);
164 char Command[MAX_COM_SIZE], Buf[MAX_COM_SIZE];
165 time_t Time;
166
167 // Set up server socket
168 if ((ServerSocket = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
169 m->PrintMessage("Could not open server socket, no remote connection possible (%s).\n", strerror(errno));
170 return;
171 }
172 // Allows immediate reuse of socket after closing (circumvents TIME_WAIT)
173 int Value=1;
174 if (setsockopt(ServerSocket, SOL_SOCKET, SO_REUSEADDR, (char *) &Value, sizeof (Value)) == -1) {
175 m->PrintMessage("Warning: Could not set server socket option SO_REUSEADDR (%s)\n", strerror(errno));
176 }
177
178 SocketAddress.sin_family = PF_INET;
179 SocketAddress.sin_port = htons((unsigned short) m->fCCPort);
180 SocketAddress.sin_addr.s_addr = INADDR_ANY;
181 if (bind(ServerSocket, (struct sockaddr *) &SocketAddress, sizeof(SocketAddress)) == -1)
182 {
183 m->PrintMessage("Could not bind port to socket (%s)\n", strerror(errno));
184 close(ServerSocket);
185 return;
186 }
187 if (listen(ServerSocket, 0) == -1) {
188 m->PrintMessage("Could not set socket to listening (%s)\n", strerror(errno));
189 close(ServerSocket);
190 return;
191 }
192
193 // Looping to wait for incoming connection
194 while (!m->Exit) {
195 if ((ConnectionSocket = accept(ServerSocket, (struct sockaddr *) &ClientAddress, &SizeClientAddress)) == -1) {
196 if (errno!=EINTR) m->PrintMessage("Failed to accept incoming connection (%s)\n", strerror(errno));
197 close(ServerSocket);
198 return;
199 }
200
201 ClientName = gethostbyaddr((char *) &ClientAddress.sin_addr ,sizeof(struct sockaddr_in),AF_INET);
202 m->PrintMessage("Connected to client at %s (%s).\n", inet_ntoa(ClientAddress.sin_addr), ClientName!=NULL ? ClientName->h_name:"name unknown");
203 m->Socket = ConnectionSocket;
204
205 while (!m->Exit) { // Looping as long as client exists
206 memset(Command,0,sizeof(Command));
207 ReadResult = read(ConnectionSocket, Command, MAX_COM_SIZE);
208 if (ReadResult==0) break; // Client no exisiting anymore
209 if (ReadResult==-1) {
210 if (errno!=EINTR) m->PrintMessage("Error read from socket (%s)\n", strerror(errno));
211 break;
212 }
213
214 strftime(Buf,MAX_COM_SIZE,"%d/%m/%y %X", localtime(&(Time=time(NULL))));
215 m->PrintMessage(MsgToLog,"SOCKET(%s)> %s%s",Buf, Command, Command[strlen(Command)-1]=='\n' ? "":"\n");
216 m->PrintMessage(MsgToConsole,"SOCKET> %s%s",Command, Command[strlen(Command)-1]=='\n' ? "":"\n");
217
218 pthread_mutex_lock(&m->control_mutex);
219 m->CommandControl(Command, true); // Process CC command
220 pthread_mutex_unlock(&m->control_mutex);
221 m->PrintMessage(""); // New prompt
222 }
223 m->Socket = -1;
224 m->PrintMessage("Disconnected from client.\n");
225 close(ConnectionSocket);
226 }
227 close(ServerSocket);
228 m->PrintMessage("Server socket closed.\n");
229}
230
231
232/********************************************************************\
233
234 Signal handlers
235
236\********************************************************************/
237
238// Remove lock file before running default signal code
239void CrashHandler(int Signal) {
240 remove(LOCKFILE);
241 printf("Caught signal number %d. Removing lockfile and performing standard signal action. Good luck.\n",Signal);
242 signal(Signal, SIG_DFL);
243 raise(Signal);
244}
245
246// Dummy signal handler to return from blocking syscalls
247void SignalHandler(int Signal) {
248 return;
249}
Note: See TracBrowser for help on using the repository browser.