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