source: drsdaq/drsdaq.cpp@ 37

Last change on this file since 37 was 36, checked in by ogrimm, 15 years ago
Various changes, see History.txt
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 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
173 SocketAddress.sin_family = PF_INET;
174 SocketAddress.sin_port = htons((unsigned short) m->fCCPort);
175 SocketAddress.sin_addr.s_addr = INADDR_ANY;
176 if (bind(ServerSocket, (struct sockaddr *) &SocketAddress, sizeof(SocketAddress)) == -1)
177 {
178 m->PrintMessage("Could not bind port to socket (%s)\n", strerror(errno));
179 close(ServerSocket);
180 return;
181 }
182 if (listen(ServerSocket, 0) == -1) {
183 m->PrintMessage("Could not set socket to listening (%s)\n", strerror(errno));
184 close(ServerSocket);
185 return;
186 }
187
188 // Looping to wait for incoming connection
189 while (!m->Exit) {
190 if ((ConnectionSocket = accept(ServerSocket, (struct sockaddr *) &ClientAddress, &SizeClientAddress)) == -1) {
191 if (errno!=EINTR) m->PrintMessage("Failed to accept incoming connection (%s)\n", strerror(errno));
192 close(ServerSocket);
193 return;
194 }
195
196 ClientName = gethostbyaddr((char *) &ClientAddress.sin_addr ,sizeof(struct sockaddr_in),AF_INET);
197 m->PrintMessage("Connected to client at %s (%s).\n", inet_ntoa(ClientAddress.sin_addr), ClientName!=NULL ? ClientName->h_name:"name unknown");
198 m->Socket = ConnectionSocket;
199
200 while (!m->Exit) { // Looping as long as client exists
201 memset(Command,0,sizeof(Command));
202 ReadResult = read(ConnectionSocket, Command, MAX_COM_SIZE);
203 if (ReadResult==0) break; // Client no exisiting anymore
204 if (ReadResult==-1) {
205 if (errno!=EINTR) m->PrintMessage("Error read from socket (%s)\n", strerror(errno));
206 break;
207 }
208
209 strftime(Buf,MAX_COM_SIZE,"%d/%m/%y %X", localtime(&(Time=time(NULL))));
210 m->PrintMessage(MsgToLog,"SOCKET(%s)> %s%s",Buf, Command, Command[strlen(Command)-1]=='\n' ? "":"\n");
211 m->PrintMessage(MsgToConsole,"SOCKET> %s%s",Command, Command[strlen(Command)-1]=='\n' ? "":"\n");
212
213 pthread_mutex_lock(&m->control_mutex);
214 m->CommandControl(Command, true); // Process CC command
215 pthread_mutex_unlock(&m->control_mutex);
216 m->PrintMessage(""); // New prompt
217 }
218 m->Socket = -1;
219 m->PrintMessage("Disconnected from client.\n");
220 close(ConnectionSocket);
221 }
222 close(ServerSocket);
223 m->PrintMessage("Server socket closed.\n");
224}
225
226
227/********************************************************************\
228
229 Signal handlers
230
231\********************************************************************/
232
233// Remove lock file before running default signal code
234void CrashHandler(int Signal) {
235 remove(LOCKFILE);
236 printf("Caught signal number %d. Removing lockfile and performing standard signal action. Good luck.\n",Signal);
237 signal(Signal, SIG_DFL);
238 raise(Signal);
239}
240
241// Dummy signal handler to return from blocking syscalls
242void SignalHandler(int Signal) {
243 return;
244}
Note: See TracBrowser for help on using the repository browser.