diff --git a/configure.in b/configure.in index 6a7d7dec4d..b74e973a4a 100644 --- a/configure.in +++ b/configure.in @@ -474,7 +474,7 @@ AC_PROG_GCC_TRADITIONAL AC_FUNC_MALLOC AC_TYPE_SIGNAL AC_FUNC_STRFTIME -AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs timerfd_create]) +AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs timerfd_create getdtablesize]) AC_CHECK_FUNCS([sched_setscheduler setpriority setrlimit setgroups initgroups]) AC_CHECK_FUNCS([wcsncmp setgroups asprintf setenv pselect gettimeofday localtime_r gmtime_r strcasecmp stricmp _stricmp]) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 51ed3587e5..97fbc942af 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -306,7 +306,8 @@ typedef enum { SCF_AUTO_SCHEMAS = (1 << 13), SCF_MINIMAL = (1 << 14), SCF_USE_NAT_MAPPING = (1 << 15), - SCF_CLEAR_SQL = (1 << 16) + SCF_CLEAR_SQL = (1 << 16), + SCF_THREADED_SYSTEM_EXEC = (1 << 17) } switch_core_flag_enum_t; typedef uint32_t switch_core_flag_t; @@ -1677,7 +1678,8 @@ typedef enum { SCSC_VERBOSE_EVENTS, SCSC_SHUTDOWN_CHECK, SCSC_PAUSE_CHECK, - SCSC_READY_CHECK + SCSC_READY_CHECK, + SCSC_THREADED_SYSTEM_EXEC } switch_session_ctl_t; typedef enum { diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index dba27031b1..a5175299be 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -1840,6 +1840,15 @@ SWITCH_STANDARD_API(ctl_function) switch_core_session_ctl(SCSC_VERBOSE_EVENTS, &arg); stream->write_function(stream, "+OK verbose_events is %s \n", arg ? "on" : "off"); + } else if (!strcasecmp(argv[0], "threaded_system_exec")) { + arg = -1; + if (argv[1]) { + arg = switch_true(argv[1]); + } + + switch_core_session_ctl(SCSC_THREADED_SYSTEM_EXEC, &arg); + + stream->write_function(stream, "+OK threaded_system_exec is %s \n", arg ? "true" : "false"); } else if (!strcasecmp(argv[0], "save_history")) { switch_core_session_ctl(SCSC_SAVE_HISTORY, NULL); diff --git a/src/switch.c b/src/switch.c index 401829cf82..4ef38111f2 100644 --- a/src/switch.c +++ b/src/switch.c @@ -102,6 +102,7 @@ static void handle_SIGCHLD(int sig) pid = wait(&status); if (pid > 0) { + printf("ASS %d\n", pid); system_ready = -1; } diff --git a/src/switch_core.c b/src/switch_core.c index e9e5b3871c..ba0350a7fe 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -647,6 +647,41 @@ SWITCH_DECLARE(void) switch_core_set_globals(void) switch_assert(SWITCH_GLOBAL_dirs.temp_dir); } + +static int32_t set_low_priority(void) +{ +#ifdef WIN32 + SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); +#else +#ifdef USE_SCHED_SETSCHEDULER + /* + * Try to use a normal scheduler + */ + struct sched_param sched = { 0 }; + sched.sched_priority = 0; + if (sched_setscheduler(0, SCHED_OTHER, &sched)) { + return -1; + } +#endif + +#ifdef HAVE_SETPRIORITY + /* + * setpriority() works on FreeBSD (6.2), nice() doesn't + */ + if (setpriority(PRIO_PROCESS, getpid(), 19) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); + return -1; + } +#else + if (nice(19) != 19) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); + return -1; + } +#endif +#endif + return 0; +} + static int32_t set_priority(void) { #ifdef WIN32 @@ -1359,6 +1394,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc switch_set_flag((&runtime.dummy_cng_frame), SFF_CNG); switch_set_flag((&runtime), SCF_AUTO_SCHEMAS); switch_set_flag((&runtime), SCF_CLEAR_SQL); + switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); runtime.hard_log_level = SWITCH_LOG_DEBUG; @@ -1483,6 +1519,24 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc } +#ifndef WIN32 +static void handle_SIGCHLD(int sig) +{ + int status = 0; + int pid = 0; + + if (sig); + + pid = wait(&status); + + if (pid > 0) { + printf("ASS %d\n", pid); + } + + return; +} +#endif + #ifdef TRAP_BUS static void handle_SIGBUS(int sig) { @@ -1690,6 +1744,17 @@ static void switch_load_core_config(const char *file) } else { switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS); } + } else if (!strcasecmp(var, "threaded-system-exec") && !zstr(val)) { +#ifdef WIN32 + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "threaded-system-exec is not implemented on this platform\n"); +#else + int v = switch_true(val); + if (v) { + switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } else { + switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } +#endif } else if (!strcasecmp(var, "min-idle-cpu") && !zstr(val)) { switch_core_min_idle_cpu(atof(val)); } else if (!strcasecmp(var, "tipping-point") && !zstr(val)) { @@ -1870,7 +1935,9 @@ SWITCH_DECLARE(void) switch_core_set_signal_handlers(void) { /* set signal handlers */ signal(SIGINT, SIG_IGN); - +#ifndef WIN32 + signal(SIGCHLD, handle_SIGCHLD); +#endif #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif @@ -1924,6 +1991,18 @@ SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void * newintval = switch_test_flag((&runtime), SCF_VERBOSE_EVENTS); } break; + case SCSC_THREADED_SYSTEM_EXEC: + if (intval) { + if (oldintval > -1) { + if (oldintval) { + switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } else { + switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } + } + newintval = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } + break; case SCSC_CALIBRATE_CLOCK: switch_time_calibrate_clock(); break; @@ -2256,7 +2335,8 @@ static void *SWITCH_THREAD_FUNC system_thread(switch_thread_t *thread, void *obj return NULL; } -SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait) + +static int switch_system_thread(const char *cmd, switch_bool_t wait) { switch_thread_t *thread; switch_threadattr_t *thd_attr; @@ -2296,6 +2376,68 @@ SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait) } +#ifdef WIN32 +static int switch_system_fork(const char *cmd, switch_bool_t wait) +{ + return switch_system_thread(cmd, wait); +} + +#else +static int max_open(void) +{ + int max; + +#if defined(HAVE_GETDTABLESIZE) + max = getdtablesize(); +#else + max = sysconf(_SC_OPEN_MAX); +#endif + + return max; + +} + +static int switch_system_fork(const char *cmd, switch_bool_t wait) +{ + int pid; + + switch_core_set_signal_handlers(); + + pid = fork(); + + if (pid) { + if (wait) { + waitpid(pid, NULL, 0); + } + } else { + int open_max = max_open(); + int i; + + for (i = 3; i < open_max; i++) { + close(i); + } + + set_low_priority(); + system(cmd); + exit(0); + } + + return 0; +} +#endif + + + +SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait) +{ + int (*sys_p)(const char *cmd, switch_bool_t wait); + + sys_p = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC) ? switch_system_thread : switch_system_fork; + + return sys_p(cmd, wait); + +} + /* For Emacs: * Local Variables: