ddd0242c8c7587d52bc1f7c2d260f677a84071c1
[deliverable/titan.core.git] / core / Parallel_main.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <errno.h>
13 #include <netdb.h>
14 #include <time.h>
15
16 #include "../common/dbgnew.hh"
17 #include "../common/version_internal.h"
18 #include "Logger.hh"
19 #include "Snapshot.hh"
20 #include "Port.hh"
21 #include "Module_list.hh"
22 #include "Runtime.hh"
23 #include "Component.hh"
24 #include "Error.hh"
25 #include "Encdec.hh"
26 #include "TCov.hh"
27
28 #ifdef LICENSE
29 #include "../common/license.h"
30 #endif
31
32 #include <signal.h>
33
34 const char * stored_argv = "Unidentified program";
35
36 //static const char segfault[] = " : Segmentation fault occurred\n";
37
38 void signal_handler(int)
39 {
40 int retval;
41 time_t now=time(0);
42 char ts[60];
43 ts[0]='\0';
44 struct tm *tmp;
45 tmp=localtime(&now);
46 if(tmp==NULL){
47 fprintf(stderr,"<Unknown> %s: Segmentation fault occurred\n",stored_argv);
48 } else {
49 /* retval = write(STDERR_FILENO, stored_argv, strlen(stored_argv));
50 retval = write(STDERR_FILENO, segfault , sizeof(segfault)-1); // sizeof includes \0
51 fflush(stderr);
52 (void)retval;
53 */
54 retval=strftime(ts,60,"%F %T",tmp);
55 fprintf(stderr,"%s %s: Segmentation fault occurred\n",ts,stored_argv);
56 }
57 fflush(stderr);
58
59 abort();
60 }
61
62 static void usage(const char* program_name)
63 {
64 fprintf(stderr, "\n"
65 "usage: %s [-s local_addr] MC_host MC_port\n"
66 " or %s -l\n"
67 " or %s -v\n"
68 "\n"
69 "OPTIONS:\n"
70 " -s local_addr: use the given source IP address for control "
71 "connections\n"
72 " -l: list startable test cases and control parts\n"
73 " -v: show version and module information\n",
74 program_name, program_name, program_name);
75 }
76
77 /** Returns whether the caller should exit immediately */
78 static boolean process_options(int argc, char *argv[], int& ret_val,
79 const char*& local_addr, const char*& MC_host, unsigned short& MC_port)
80 {
81 boolean lflag = FALSE, sflag = FALSE, vflag = FALSE, errflag = FALSE;
82 for ( ; ; ) {
83 int c = getopt(argc, argv, "ls:v");
84 if (c == -1) break;
85 switch (c) {
86 case 'l':
87 if (lflag || sflag || vflag) errflag = TRUE;
88 else lflag = TRUE;
89 break;
90 case 's':
91 if (lflag || sflag || vflag) errflag = TRUE;
92 else {
93 local_addr = optarg;
94 sflag = TRUE;
95 }
96 break;
97 case 'v':
98 if (lflag || sflag || vflag) errflag = TRUE;
99 else vflag = TRUE;
100 break;
101 default:
102 errflag = TRUE;
103 break;
104 }
105 }
106
107 if (lflag || vflag) {
108 if (optind != argc) errflag = TRUE;
109 } else {
110 if (optind == argc - 2) {
111 MC_host = argv[optind++];
112 int port_num = atoi(argv[optind]);
113 if (port_num > 0 && port_num < 65536) MC_port = port_num;
114 else {
115 fprintf(stderr, "Invalid MC port: %s\n", argv[optind]);
116 errflag = TRUE;
117 }
118 } else errflag = TRUE;
119 }
120
121 if (errflag) {
122 // syntax error in command line
123 if (argc == 1) fputs("TTCN-3 Host Controller (parallel mode), version "
124 PRODUCT_NUMBER "\n", stderr);
125 usage(argv[0]);
126 ret_val = EXIT_FAILURE;
127 return TRUE;
128 } else if (lflag) {
129 // list of testcases
130 try {
131 // create buffer for error messages
132 TTCN_Runtime::install_signal_handlers();
133 TTCN_Logger::initialize_logger();
134 Module_List::pre_init_modules();
135 Module_List::list_testcases();
136 } catch (...) {
137 ret_val = EXIT_FAILURE;
138 }
139 TTCN_Logger::terminate_logger();
140 return TRUE;
141 } else if (vflag) {
142 // version printout
143 fputs("TTCN-3 Host Controller (parallel mode)\n"
144 "Product number: " PRODUCT_NUMBER "\n"
145 "Build date (Base Library): " __DATE__ " " __TIME__ "\n"
146 "Base Library was compiled with: " C_COMPILER_VERSION "\n\n"
147 COPYRIGHT_STRING "\n\n", stderr);
148 #ifdef LICENSE
149 print_license_info();
150 putc('\n', stderr);
151 #endif
152 fputs("Module information:\n", stderr);
153 Module_List::print_version();
154 return TRUE;
155 }
156 // normal usage (HC operation)
157 fputs("TTCN-3 Host Controller (parallel mode), version " PRODUCT_NUMBER
158 "\n", stderr);
159 #ifdef LICENSE
160 init_openssl();
161 license_struct lstr;
162 load_license(&lstr);
163 if (!verify_license(&lstr)) {
164 free_license(&lstr);
165 free_openssl();
166 exit(EXIT_FAILURE);
167 }
168 if (!check_feature(&lstr, FEATURE_HC)) {
169 fputs("The license key does not allow the starting of TTCN-3 "
170 "Host Controllers.\n", stderr);
171 ret_val = EXIT_FAILURE;
172 }
173 free_license(&lstr);
174 free_openssl();
175 if (ret_val != EXIT_SUCCESS) return TRUE;
176 #endif
177 return FALSE;
178 }
179
180 int main(int argc, char *argv[])
181 {
182 stored_argv = argv[0];
183 struct sigaction act;
184 act.sa_handler = signal_handler;
185 sigemptyset(&act.sa_mask);
186 act.sa_flags = 0;
187 sigaction(SIGSEGV, &act, 0);
188
189 #ifdef MEMORY_DEBUG
190 debug_new_counter.set_program_name(argv[0]);
191 #endif
192 int ret_val = EXIT_SUCCESS;
193 const char *local_addr = NULL, *MC_host = NULL;
194 unsigned short MC_port = 0;
195 errno = 0;
196
197 if (process_options(argc, argv, ret_val, local_addr, MC_host, MC_port)) {
198 TCov::close_file();
199 return ret_val;
200 }
201
202 try {
203 TTCN_Runtime::install_signal_handlers();
204 TTCN_Snapshot::initialize();
205 TTCN_Logger::initialize_logger();
206 TTCN_Logger::set_executable_name(argv[0]);
207 TTCN_Logger::set_start_time();
208
209 // the log file will be opened immediately after processing
210 // configuration data received from the MC
211
212 try {
213 Module_List::pre_init_modules();
214 ret_val = TTCN_Runtime::hc_main(local_addr, MC_host, MC_port);
215 if (!TTCN_Runtime::is_hc()) {
216 // this code runs on the child processes (MTC and PTCs)
217 // forget about the component names inherited from the HC
218 COMPONENT::clear_component_names();
219 // the log file is inherited from the parent process
220 // it has to be closed first
221 TTCN_Logger::close_file();
222 TCov::close_file();
223 // the baseline of relative timestamps has to be reset
224 TTCN_Logger::set_start_time();
225
226 if (TTCN_Runtime::is_mtc()) ret_val = TTCN_Runtime::mtc_main();
227 else if (TTCN_Runtime::is_ptc())
228 ret_val = TTCN_Runtime::ptc_main();
229 else TTCN_error("Internal error: Invalid executor state after "
230 "finishing HC activities.");
231 }
232 } catch (const TC_Error& TC_error) {
233 ret_val = EXIT_FAILURE;
234 }
235 } catch (...) {
236 TTCN_Logger::log_str(TTCN_Logger::ERROR_UNQUALIFIED,
237 "Fatal error. Aborting execution.");
238 ret_val = EXIT_FAILURE;
239 }
240 // the final cleanup tasks are common for all processes
241 TTCN_Runtime::restore_signal_handlers();
242 TTCN_Logger::close_file();
243 TCov::close_file();
244 // close_file() must be called before the information is lost
245 // close_file() WRITES to log
246 TTCN_Logger::clear_parameters();
247 PORT::clear_parameters();
248 COMPONENT::clear_component_names();
249 TTCN_EncDec::clear_error();
250
251 TTCN_Logger::terminate_logger();
252 TTCN_Snapshot::terminate();
253
254 return ret_val;
255 }
This page took 0.044063 seconds and 5 git commands to generate.