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