|
|
|
@ -51,6 +51,7 @@ using namespace std;
|
|
|
|
|
// pre-declare
|
|
|
|
|
int run(SrsServer* svr);
|
|
|
|
|
int run_master(SrsServer* svr);
|
|
|
|
|
void show_macro_features();
|
|
|
|
|
|
|
|
|
|
// @global log and context.
|
|
|
|
|
ISrsLog* _srs_log = new SrsFastLog();
|
|
|
|
@ -62,8 +63,113 @@ SrsConfig* _srs_config = new SrsConfig();
|
|
|
|
|
extern const char* _srs_version;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* show the features by macro, the actual macro values.
|
|
|
|
|
* main entrance.
|
|
|
|
|
*/
|
|
|
|
|
int main(int argc, char** argv)
|
|
|
|
|
{
|
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
|
|
// TODO: support both little and big endian.
|
|
|
|
|
srs_assert(srs_is_little_endian());
|
|
|
|
|
|
|
|
|
|
// for gperf gmp or gcp,
|
|
|
|
|
// should never enable it when not enabled for performance issue.
|
|
|
|
|
#ifdef SRS_AUTO_GPERF_MP
|
|
|
|
|
HeapProfilerStart("gperf.srs.gmp");
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SRS_AUTO_GPERF_CP
|
|
|
|
|
ProfilerStart("gperf.srs.gcp");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// directly compile error when these two macro defines.
|
|
|
|
|
#if defined(SRS_AUTO_GPERF_MC) && defined(SRS_AUTO_GPERF_MP)
|
|
|
|
|
#error ("option --with-gmc confict with --with-gmp, "
|
|
|
|
|
"@see: http://google-perftools.googlecode.com/svn/trunk/doc/heap_checker.html\n"
|
|
|
|
|
"Note that since the heap-checker uses the heap-profiling framework internally, "
|
|
|
|
|
"it is not possible to run both the heap-checker and heap profiler at the same time");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// never use gmp to check memory leak.
|
|
|
|
|
#ifdef SRS_AUTO_GPERF_MP
|
|
|
|
|
#warning "gmp is not used for memory leak, please use gmc instead."
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// never use srs log(srs_trace, srs_error, etc) before config parse the option,
|
|
|
|
|
// which will load the log config and apply it.
|
|
|
|
|
if ((ret = _srs_config->parse_options(argc, argv)) != ERROR_SUCCESS) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// change the work dir and set cwd.
|
|
|
|
|
string cwd = _srs_config->get_work_dir();
|
|
|
|
|
if (!cwd.empty() && cwd != "./" && (ret = chdir(cwd.c_str())) != ERROR_SUCCESS) {
|
|
|
|
|
srs_error("change cwd to %s failed. ret=%d", cwd.c_str(), ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
if ((ret = _srs_config->initialize_cwd()) != ERROR_SUCCESS) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// config parsed, initialize log.
|
|
|
|
|
if ((ret = _srs_log->initialize()) != ERROR_SUCCESS) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// config already applied to log.
|
|
|
|
|
srs_trace(RTMP_SIG_SRS_SERVER", stable is "RTMP_SIG_SRS_PRIMARY);
|
|
|
|
|
srs_trace("license: "RTMP_SIG_SRS_LICENSE", "RTMP_SIG_SRS_COPYRIGHT);
|
|
|
|
|
srs_trace("authors: "RTMP_SIG_SRS_AUTHROS);
|
|
|
|
|
srs_trace("contributors: "SRS_AUTO_CONSTRIBUTORS);
|
|
|
|
|
srs_trace("build: %s, configure:%s, uname: %s", SRS_AUTO_BUILD_DATE, SRS_AUTO_USER_CONFIGURE, SRS_AUTO_UNAME);
|
|
|
|
|
srs_trace("configure detail: "SRS_AUTO_CONFIGURE);
|
|
|
|
|
#ifdef SRS_AUTO_EMBEDED_TOOL_CHAIN
|
|
|
|
|
srs_trace("crossbuild tool chain: "SRS_AUTO_EMBEDED_TOOL_CHAIN);
|
|
|
|
|
#endif
|
|
|
|
|
srs_trace("cwd=%s, work_dir=%s", _srs_config->cwd().c_str(), cwd.c_str());
|
|
|
|
|
|
|
|
|
|
#ifdef SRS_PERF_GLIBC_MEMORY_CHECK
|
|
|
|
|
// ensure glibc write error to stderr.
|
|
|
|
|
setenv("LIBC_FATAL_STDERR_", "1", 1);
|
|
|
|
|
// ensure glibc to do alloc check.
|
|
|
|
|
setenv("MALLOC_CHECK_", "1", 1);
|
|
|
|
|
srs_trace("env MALLOC_CHECK_=1 LIBC_FATAL_STDERR_=1");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef SRS_AUTO_GPERF_MD
|
|
|
|
|
char* TCMALLOC_PAGE_FENCE = getenv("TCMALLOC_PAGE_FENCE");
|
|
|
|
|
if (!TCMALLOC_PAGE_FENCE || strcmp(TCMALLOC_PAGE_FENCE, "1")) {
|
|
|
|
|
srs_trace("gmd enabled without env TCMALLOC_PAGE_FENCE=1");
|
|
|
|
|
} else {
|
|
|
|
|
srs_trace("env TCMALLOC_PAGE_FENCE=1");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// we check the config when the log initialized.
|
|
|
|
|
if ((ret = _srs_config->check_config()) != ERROR_SUCCESS) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// features
|
|
|
|
|
show_macro_features();
|
|
|
|
|
|
|
|
|
|
SrsServer* svr = new SrsServer();
|
|
|
|
|
SrsAutoFree(SrsServer, svr);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* we do nothing in the constructor of server,
|
|
|
|
|
* and use initialize to create members, set hooks for instance the reload handler,
|
|
|
|
|
* all initialize will done in this stage.
|
|
|
|
|
*/
|
|
|
|
|
if ((ret = svr->initialize(NULL)) != ERROR_SUCCESS) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return run(svr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* show the features by macro, the actual macro values.
|
|
|
|
|
*/
|
|
|
|
|
void show_macro_features()
|
|
|
|
|
{
|
|
|
|
|
if (true) {
|
|
|
|
@ -135,8 +241,8 @@ void show_macro_features()
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
ss << ", conf:" << _srs_config->config() << ", limit:" << _srs_config->get_max_connections()
|
|
|
|
|
<< ", writev:" << sysconf(_SC_IOV_MAX) << ", encoding:" << (srs_is_little_endian()? "little-endian":"big-endian")
|
|
|
|
|
<< ", HZ:" << (int)sysconf(_SC_CLK_TCK);
|
|
|
|
|
<< ", writev:" << sysconf(_SC_IOV_MAX) << ", encoding:" << (srs_is_little_endian()? "little-endian":"big-endian")
|
|
|
|
|
<< ", HZ:" << (int)sysconf(_SC_CLK_TCK);
|
|
|
|
|
|
|
|
|
|
srs_trace(ss.str().c_str());
|
|
|
|
|
}
|
|
|
|
@ -184,7 +290,7 @@ void show_macro_features()
|
|
|
|
|
#else
|
|
|
|
|
ss << "off";
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ss(SO_SENDBUF)
|
|
|
|
|
ss << ", ss:";
|
|
|
|
|
#ifdef SRS_PERF_SO_SNDBUF_SIZE
|
|
|
|
@ -205,130 +311,25 @@ void show_macro_features()
|
|
|
|
|
SRS_PERF_MW_SLEEP, possible_mr_latency, SRS_PERF_PLAY_QUEUE*1000);
|
|
|
|
|
|
|
|
|
|
#ifdef SRS_AUTO_MEM_WATCH
|
|
|
|
|
#warning "srs memory watcher will hurts performance. user should kill by SIGTERM or init.d script."
|
|
|
|
|
#warning "srs memory watcher will hurts performance. user should kill by SIGTERM or init.d script."
|
|
|
|
|
srs_warn("srs memory watcher will hurts performance. user should kill by SIGTERM or init.d script.");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(SRS_AUTO_STREAM_CASTER)
|
|
|
|
|
#warning "stream caster is experiment feature."
|
|
|
|
|
#warning "stream caster is experiment feature."
|
|
|
|
|
srs_warn("stream caster is experiment feature.");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if VERSION_MAJOR > VERSION_STABLE
|
|
|
|
|
#warning "current branch is not stable, please use stable branch instead."
|
|
|
|
|
#warning "current branch is not stable, please use stable branch instead."
|
|
|
|
|
srs_warn("SRS %s is not stable, please use stable branch %s instead", RTMP_SIG_SRS_VERSION, VERSION_STABLE_BRANCH);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(SRS_PERF_SO_SNDBUF_SIZE) && !defined(SRS_PERF_MW_SO_SNDBUF)
|
|
|
|
|
#error "SRS_PERF_SO_SNDBUF_SIZE depends on SRS_PERF_MW_SO_SNDBUF"
|
|
|
|
|
#error "SRS_PERF_SO_SNDBUF_SIZE depends on SRS_PERF_MW_SO_SNDBUF"
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* main entrance.
|
|
|
|
|
*/
|
|
|
|
|
int main(int argc, char** argv)
|
|
|
|
|
{
|
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
|
|
// TODO: support both little and big endian.
|
|
|
|
|
srs_assert(srs_is_little_endian());
|
|
|
|
|
|
|
|
|
|
// for gperf gmp or gcp,
|
|
|
|
|
// should never enable it when not enabled for performance issue.
|
|
|
|
|
#ifdef SRS_AUTO_GPERF_MP
|
|
|
|
|
HeapProfilerStart("gperf.srs.gmp");
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SRS_AUTO_GPERF_CP
|
|
|
|
|
ProfilerStart("gperf.srs.gcp");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// directly compile error when these two macro defines.
|
|
|
|
|
#if defined(SRS_AUTO_GPERF_MC) && defined(SRS_AUTO_GPERF_MP)
|
|
|
|
|
#error ("option --with-gmc confict with --with-gmp, "
|
|
|
|
|
"@see: http://google-perftools.googlecode.com/svn/trunk/doc/heap_checker.html\n"
|
|
|
|
|
"Note that since the heap-checker uses the heap-profiling framework internally, "
|
|
|
|
|
"it is not possible to run both the heap-checker and heap profiler at the same time");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// never use gmp to check memory leak.
|
|
|
|
|
#ifdef SRS_AUTO_GPERF_MP
|
|
|
|
|
#warning "gmp is not used for memory leak, please use gmc instead."
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// never use srs log(srs_trace, srs_error, etc) before config parse the option,
|
|
|
|
|
// which will load the log config and apply it.
|
|
|
|
|
if ((ret = _srs_config->parse_options(argc, argv)) != ERROR_SUCCESS) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// change the work dir and set cwd.
|
|
|
|
|
string cwd = _srs_config->get_work_dir();
|
|
|
|
|
if (!cwd.empty() && cwd != "./" && (ret = chdir(cwd.c_str())) != ERROR_SUCCESS) {
|
|
|
|
|
srs_error("change cwd to %s failed. ret=%d", cwd.c_str(), ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
if ((ret = _srs_config->initialize_cwd()) != ERROR_SUCCESS) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// config parsed, initialize log.
|
|
|
|
|
if ((ret = _srs_log->initialize()) != ERROR_SUCCESS) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// config already applied to log.
|
|
|
|
|
srs_trace(RTMP_SIG_SRS_SERVER", stable is "RTMP_SIG_SRS_PRIMARY);
|
|
|
|
|
srs_trace("license: "RTMP_SIG_SRS_LICENSE", "RTMP_SIG_SRS_COPYRIGHT);
|
|
|
|
|
srs_trace("authors: "RTMP_SIG_SRS_AUTHROS);
|
|
|
|
|
srs_trace("contributors: "SRS_AUTO_CONSTRIBUTORS);
|
|
|
|
|
srs_trace("build: %s, configure:%s, uname: %s", SRS_AUTO_BUILD_DATE, SRS_AUTO_USER_CONFIGURE, SRS_AUTO_UNAME);
|
|
|
|
|
srs_trace("configure detail: "SRS_AUTO_CONFIGURE);
|
|
|
|
|
#ifdef SRS_AUTO_EMBEDED_TOOL_CHAIN
|
|
|
|
|
srs_trace("crossbuild tool chain: "SRS_AUTO_EMBEDED_TOOL_CHAIN);
|
|
|
|
|
#endif
|
|
|
|
|
srs_trace("cwd=%s, work_dir=%s", _srs_config->cwd().c_str(), cwd.c_str());
|
|
|
|
|
|
|
|
|
|
#ifdef SRS_PERF_GLIBC_MEMORY_CHECK
|
|
|
|
|
// ensure glibc write error to stderr.
|
|
|
|
|
setenv("LIBC_FATAL_STDERR_", "1", 1);
|
|
|
|
|
// ensure glibc to do alloc check.
|
|
|
|
|
setenv("MALLOC_CHECK_", "1", 1);
|
|
|
|
|
srs_trace("env MALLOC_CHECK_=1 LIBC_FATAL_STDERR_=1");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef SRS_AUTO_GPERF_MD
|
|
|
|
|
char* TCMALLOC_PAGE_FENCE = getenv("TCMALLOC_PAGE_FENCE");
|
|
|
|
|
if (!TCMALLOC_PAGE_FENCE || strcmp(TCMALLOC_PAGE_FENCE, "1")) {
|
|
|
|
|
srs_trace("gmd enabled without env TCMALLOC_PAGE_FENCE=1");
|
|
|
|
|
} else {
|
|
|
|
|
srs_trace("env TCMALLOC_PAGE_FENCE=1");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// we check the config when the log initialized.
|
|
|
|
|
if ((ret = _srs_config->check_config()) != ERROR_SUCCESS) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// features
|
|
|
|
|
show_macro_features();
|
|
|
|
|
|
|
|
|
|
SrsServer* svr = new SrsServer();
|
|
|
|
|
SrsAutoFree(SrsServer, svr);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* we do nothing in the constructor of server,
|
|
|
|
|
* and use initialize to create members, set hooks for instance the reload handler,
|
|
|
|
|
* all initialize will done in this stage.
|
|
|
|
|
*/
|
|
|
|
|
if ((ret = svr->initialize(NULL)) != ERROR_SUCCESS) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return run(svr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int run(SrsServer* svr)
|
|
|
|
|
{
|
|
|
|
|
// if not deamon, directly run master.
|
|
|
|
|