static VOID WINAPI ServiceCtrlHandler(DWORD ctrlCode) { serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState = SERVICE_RUNNING; serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; serviceStatus.dwWin32ExitCode = 0; serviceStatus.dwServiceSpecificExitCode = 0; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWaitHint = 0; switch (ctrlCode) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; serviceStatus.dwWaitHint = 4000; SetServiceStatus(serviceHandle, &serviceStatus); /* notify other threads and allow them to terminate */ ZBX_DO_EXIT(); zbx_free_service_resources(); serviceStatus.dwCurrentState = SERVICE_STOPPED; serviceStatus.dwWaitHint = 0; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWin32ExitCode = 0; break; default: break; } SetServiceStatus(serviceHandle, &serviceStatus); }
ZBX_THREAD_ENTRY(listener_thread, args) { int ret, local_request_failed = 0; zbx_sock_t s; assert(args); assert(((zbx_thread_args_t *)args)->args); process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; process_num = ((zbx_thread_args_t *)args)->process_num; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_daemon_type_string(daemon_type), server_num, get_process_type_string(process_type), process_num); memcpy(&s, (zbx_sock_t *)((zbx_thread_args_t *)args)->args, sizeof(zbx_sock_t)); zbx_free(args); while (ZBX_IS_RUNNING()) { zbx_setproctitle("listener #%d [waiting for connection]", process_num); if (SUCCEED == (ret = zbx_tcp_accept(&s))) { local_request_failed = 0; /* reset consecutive errors counter */ zbx_setproctitle("listener #%d [processing request]", process_num); if (SUCCEED == (ret = zbx_tcp_check_security(&s, CONFIG_HOSTS_ALLOWED, 0))) process_listener(&s); zbx_tcp_unaccept(&s); } if (SUCCEED == ret || EINTR == zbx_sock_last_error()) continue; zabbix_log(LOG_LEVEL_DEBUG, "failed to accept an incoming connection: %s", zbx_tcp_strerror()); if (local_request_failed++ > 1000) { zabbix_log(LOG_LEVEL_WARNING, "too many failures to accept an incoming connection"); local_request_failed = 0; } if (ZBX_IS_RUNNING()) zbx_sleep(1); } #ifdef _WINDOWS ZBX_DO_EXIT(); zbx_thread_exit(EXIT_SUCCESS); #endif }
ZBX_THREAD_ENTRY(listener_thread, args) { int ret, local_request_failed = 0; zbx_sock_t s; assert(args); assert(((zbx_thread_args_t *)args)->args); zabbix_log(LOG_LEVEL_WARNING, "agent #%d started [listener]", ((zbx_thread_args_t *)args)->thread_num); memcpy(&s, (zbx_sock_t *)((zbx_thread_args_t *)args)->args, sizeof(zbx_sock_t)); zbx_free(args); while (ZBX_IS_RUNNING()) { zbx_setproctitle("listener [waiting for connection]"); if (SUCCEED == (ret = zbx_tcp_accept(&s))) { local_request_failed = 0; /* reset consecutive errors counter */ zbx_setproctitle("listener [processing request]"); zabbix_log(LOG_LEVEL_DEBUG, "Processing request."); if (SUCCEED == (ret = zbx_tcp_check_security(&s, CONFIG_HOSTS_ALLOWED, 0))) process_listener(&s); zbx_tcp_unaccept(&s); } if (SUCCEED == ret) continue; zabbix_log(LOG_LEVEL_DEBUG, "Listener error: %s", zbx_tcp_strerror()); if (local_request_failed++ > 1000) { zabbix_log(LOG_LEVEL_WARNING, "Too many consecutive errors on accept() call."); local_request_failed = 0; } if (ZBX_IS_RUNNING()) zbx_sleep(1); } #ifdef _WINDOWS zabbix_log(LOG_LEVEL_INFORMATION, "zabbix_agentd listener stopped"); ZBX_DO_EXIT(); zbx_thread_exit(0); #endif }
static void parent_signal_handler(int sig) { switch (sig) { case SIGINT: case SIGTERM: ZBX_DO_EXIT(); zabbix_log(LOG_LEVEL_INFORMATION, "Got signal. Exiting ..."); zbx_on_exit(); break; } }
ZBX_THREAD_ENTRY(listener_thread, pSock) { int ret, local_request_failed = 0; zbx_sock_t s; assert(pSock); zbx_setproctitle("listener waiting for connection"); zabbix_log( LOG_LEVEL_INFORMATION, "zabbix_agentd listener started"); memcpy(&s, ((zbx_sock_t *)pSock), sizeof(zbx_sock_t)); while(ZBX_IS_RUNNING) { if( SUCCEED == (ret = zbx_tcp_accept(&s)) ) { local_request_failed = 0; /* Reset consecutive errors counter */ zbx_setproctitle("processing request"); zabbix_log(LOG_LEVEL_DEBUG, "Processing request."); if( SUCCEED == (ret = zbx_tcp_check_security(&s, CONFIG_HOSTS_ALLOWED, 0)) ) { process_listener(&s); } zbx_tcp_unaccept(&s); } zbx_setproctitle("listener waiting for connection"); if( SUCCEED == ret ) continue; zabbix_log(LOG_LEVEL_DEBUG, "Listener error: %s", zbx_tcp_strerror()); if (local_request_failed++ > 1000) { zabbix_log( LOG_LEVEL_WARNING, "Too many consecutive errors on accept() call."); local_request_failed = 0; } if(ZBX_IS_RUNNING) zbx_sleep(1); } zabbix_log( LOG_LEVEL_INFORMATION, "zabbix_agentd listener stopped"); ZBX_DO_EXIT(); zbx_tread_exit(0); }
/****************************************************************************** * * * Function: collector_thread * * * * Purpose: Collect system information * * * * Author: Eugene Grigorjev * * * ******************************************************************************/ ZBX_THREAD_ENTRY(collector_thread, args) { assert(args); zabbix_log(LOG_LEVEL_WARNING, "agent #%d started [collector]", ((zbx_thread_args_t *)args)->thread_num); zbx_free(args); if (SUCCEED != init_cpu_collector(&(collector->cpus))) free_cpu_collector(&(collector->cpus)); while (ZBX_IS_RUNNING()) { zbx_setproctitle("collector [processing data]"); #ifdef _WINDOWS collect_perfstat(); #else if (0 != CPU_COLLECTOR_STARTED(collector)) collect_cpustat(&(collector->cpus)); if (0 != DISKDEVICE_COLLECTOR_STARTED(collector)) collect_stats_diskdevices(); #endif #ifdef _AIX if (1 == collector->vmstat.enabled) collect_vmstat_data(&collector->vmstat); #endif zbx_setproctitle("collector [sleeping for 1 seconds]"); zbx_sleep(1); } if (CPU_COLLECTOR_STARTED(collector)) free_cpu_collector(&(collector->cpus)); #ifdef _WINDOWS free_perf_collector(); /* cpu_collector must be freed before perf_collector is freed */ #endif zabbix_log(LOG_LEVEL_INFORMATION, "zabbix_agentd collector stopped"); ZBX_DO_EXIT(); zbx_thread_exit(0); }
static VOID WINAPI ServiceCtrlHandler(DWORD ctrlCode) { serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState = SERVICE_RUNNING; serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; serviceStatus.dwWin32ExitCode = 0; serviceStatus.dwServiceSpecificExitCode = 0; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWaitHint = 0; switch(ctrlCode) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: zabbix_log(LOG_LEVEL_INFORMATION, "Zabbix Agent shutdown requested"); serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; serviceStatus.dwWaitHint = 4000; SetServiceStatus(serviceHandle, &serviceStatus); /* notify other threads and allow them to terminate */ ZBX_DO_EXIT(); zbx_sleep(1); serviceStatus.dwCurrentState = SERVICE_STOPPED; serviceStatus.dwWaitHint = 0; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWin32ExitCode = 0; zabbix_log(LOG_LEVEL_INFORMATION, "Zabbix Agent stopped. Zabbix %s (revision %s).", ZABBIX_VERSION, ZABBIX_REVISION); break; default: break; } SetServiceStatus(serviceHandle, &serviceStatus); }
ZBX_THREAD_ENTRY(active_checks_thread, args) { ZBX_THREAD_ACTIVECHK_ARGS activechk_args; #if defined(ZABBIX_DAEMON) struct sigaction phan; #endif /* ZABBIX_DAEMON */ int nextcheck = 0, nextrefresh = 0, nextsend = 0; char *p = NULL; #if defined(ZABBIX_DAEMON) phan.sa_handler = child_signal_handler; sigemptyset(&phan.sa_mask); phan.sa_flags = 0; sigaction(SIGALRM, &phan, NULL); #endif /* ZABBIX_DAEMON */ activechk_args.host = strdup(((ZBX_THREAD_ACTIVECHK_ARGS *)args)->host); activechk_args.port = ((ZBX_THREAD_ACTIVECHK_ARGS *)args)->port; assert(activechk_args.host); p = strchr(activechk_args.host,','); if(p) *p = '\0'; zabbix_log( LOG_LEVEL_INFORMATION, "zabbix_agentd active check started [%s:%u]", activechk_args.host, activechk_args.port); init_active_metrics(); while(ZBX_IS_RUNNING) { if(time(NULL) >= nextsend) { send_buffer(activechk_args.host, activechk_args.port); nextsend = (int)time(NULL) + 1; } if(time(NULL) >= nextrefresh) { zbx_setproctitle("poller [getting list of active checks]"); if(FAIL == refresh_active_checks(activechk_args.host, activechk_args.port)) { nextrefresh = (int)time(NULL) + 60; } else { nextrefresh = (int)time(NULL) + CONFIG_REFRESH_ACTIVE_CHECKS; } } if(time(NULL) >= nextcheck) { zbx_setproctitle("poller [processing active checks]"); process_active_checks(activechk_args.host, activechk_args.port); nextcheck = get_min_nextcheck(); if(FAIL == nextcheck) nextcheck = (int)time(NULL) + 60; } else { zabbix_log(LOG_LEVEL_DEBUG, "Sleeping for %d seconds", 1 ); zbx_setproctitle("poller [sleeping for %d seconds]", 1); zbx_sleep(1); } } zbx_free(activechk_args.host); free_active_metrics(); zabbix_log( LOG_LEVEL_INFORMATION, "zabbix_agentd active check stopped"); ZBX_DO_EXIT(); zbx_tread_exit(0); }
int MAIN_ZABBIX_ENTRY() { zbx_thread_args_t *thread_args; zbx_sock_t listen_sock; int i, thread_num = 0; #ifdef _WINDOWS DWORD res; #endif if (NULL == CONFIG_LOG_FILE || '\0' == *CONFIG_LOG_FILE) zabbix_open_log(LOG_TYPE_SYSLOG, CONFIG_LOG_LEVEL, NULL); else zabbix_open_log(LOG_TYPE_FILE, CONFIG_LOG_LEVEL, CONFIG_LOG_FILE); zabbix_log(LOG_LEVEL_INFORMATION, "Starting Zabbix Agent [%s]. Zabbix %s (revision %s).", CONFIG_HOSTNAME, ZABBIX_VERSION, ZABBIX_REVISION); zabbix_log(LOG_LEVEL_INFORMATION, "using configuration file: %s", CONFIG_FILE); #ifndef _WINDOWS if (FAIL == load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 1)) { zabbix_log(LOG_LEVEL_CRIT, "loading modules failed, exiting..."); exit(EXIT_FAILURE); } #endif if (0 != CONFIG_PASSIVE_FORKS) { if (FAIL == zbx_tcp_listen(&listen_sock, CONFIG_LISTEN_IP, (unsigned short)CONFIG_LISTEN_PORT)) { zabbix_log(LOG_LEVEL_CRIT, "listener failed: %s", zbx_tcp_strerror()); exit(1); } } init_collector_data(); #ifdef _WINDOWS init_perf_collector(1); load_perf_counters(CONFIG_PERF_COUNTERS); #endif load_user_parameters(CONFIG_USER_PARAMETERS); load_aliases(CONFIG_ALIASES); zbx_free_config(); /* --- START THREADS ---*/ /* allocate memory for a collector, all listeners and an active check */ threads_num = 1 + CONFIG_PASSIVE_FORKS + CONFIG_ACTIVE_FORKS; threads = zbx_calloc(threads, threads_num, sizeof(ZBX_THREAD_HANDLE)); /* start the collector thread */ thread_args = (zbx_thread_args_t *)zbx_malloc(NULL, sizeof(zbx_thread_args_t)); thread_args->thread_num = thread_num; thread_args->thread_num2 = 1; thread_args->args = NULL; threads[thread_num++] = zbx_thread_start(collector_thread, thread_args); /* start listeners */ for (i = 0; i < CONFIG_PASSIVE_FORKS; i++) { thread_args = (zbx_thread_args_t *)zbx_malloc(NULL, sizeof(zbx_thread_args_t)); thread_args->thread_num = thread_num; thread_args->thread_num2 = i + 1; thread_args->args = &listen_sock; threads[thread_num++] = zbx_thread_start(listener_thread, thread_args); } /* start active check */ for (i = 0; i < CONFIG_ACTIVE_FORKS; i++) { thread_args = (zbx_thread_args_t *)zbx_malloc(NULL, sizeof(zbx_thread_args_t)); thread_args->thread_num = thread_num; thread_args->thread_num2 = i + 1; thread_args->args = &CONFIG_ACTIVE_ARGS[i]; threads[thread_num++] = zbx_thread_start(active_checks_thread, thread_args); } #ifdef _WINDOWS set_parent_signal_handler(); /* must be called after all threads are created */ /* wait for an exiting thread */ res = WaitForMultipleObjectsEx(threads_num, threads, FALSE, INFINITE, FALSE); if (ZBX_IS_RUNNING()) { /* Zabbix agent service should either be stopped by the user in ServiceCtrlHandler() or */ /* crash. If some thread has terminated normally, it means something is terribly wrong. */ zabbix_log(LOG_LEVEL_CRIT, "One thread has terminated unexpectedly (code:%lu). Exiting ...", res); THIS_SHOULD_NEVER_HAPPEN; /* notify other threads and allow them to terminate */ ZBX_DO_EXIT(); zbx_sleep(1); } else { /* wait for the service worker thread to terminate us */ zbx_sleep(3); THIS_SHOULD_NEVER_HAPPEN; } #else while (-1 == wait(&i)) /* wait for any child to exit */ { if (EINTR != errno) { zabbix_log(LOG_LEVEL_ERR, "failed to wait on child processes: %s", zbx_strerror(errno)); break; } } /* all exiting child processes should be caught by signal handlers */ THIS_SHOULD_NEVER_HAPPEN; #endif zbx_on_exit(); return SUCCEED; }
ZBX_THREAD_ENTRY(listener_thread, args) { #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) char *msg = NULL; #endif int ret; zbx_socket_t s; assert(args); assert(((zbx_thread_args_t *)args)->args); process_type = ((zbx_thread_args_t *)args)->process_type; server_num = ((zbx_thread_args_t *)args)->server_num; process_num = ((zbx_thread_args_t *)args)->process_num; zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type), server_num, get_process_type_string(process_type), process_num); memcpy(&s, (zbx_socket_t *)((zbx_thread_args_t *)args)->args, sizeof(zbx_socket_t)); zbx_free(args); #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) zbx_tls_init_child(); #endif while (ZBX_IS_RUNNING()) { zbx_setproctitle("listener #%d [waiting for connection]", process_num); ret = zbx_tcp_accept(&s, configured_tls_accept_modes); zbx_update_env(zbx_time()); if (SUCCEED == ret) { zbx_setproctitle("listener #%d [processing request]", process_num); if ('\0' != *CONFIG_HOSTS_ALLOWED && SUCCEED == (ret = zbx_tcp_check_allowed_peers(&s, CONFIG_HOSTS_ALLOWED))) { #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) if (ZBX_TCP_SEC_TLS_CERT != s.connection_type || SUCCEED == (ret = zbx_check_server_issuer_subject(&s, &msg))) #endif { process_listener(&s); } } zbx_tcp_unaccept(&s); } if (SUCCEED == ret || EINTR == zbx_socket_last_error()) continue; #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) if (NULL != msg) { zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s", msg); zbx_free(msg); } else #endif { zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s", zbx_socket_strerror()); } if (ZBX_IS_RUNNING()) zbx_sleep(1); } #ifdef _WINDOWS ZBX_DO_EXIT(); zbx_thread_exit(EXIT_SUCCESS); #endif }