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