From bb200b5d2d76e397997abda293c077acb994d9e4 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 9 Jun 2017 11:50:35 +0800 Subject: [PATCH] For #913, add complex error. --- trunk/src/app/srs_app_server.cpp | 11 +-- trunk/src/app/srs_app_server.hpp | 2 +- trunk/src/core/srs_core.hpp | 4 + trunk/src/kernel/srs_kernel_error.cpp | 108 ++++++++++++++++++++++++++ trunk/src/kernel/srs_kernel_error.hpp | 51 ++++++++---- trunk/src/main/srs_main_server.cpp | 53 ++++++++----- 6 files changed, 190 insertions(+), 39 deletions(-) diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 5788b2fa1..d58aecfec 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -557,9 +557,10 @@ void SrsServer::dispose() #endif } -int SrsServer::initialize(ISrsServerCycle* cycle_handler) +srs_error_t SrsServer::initialize(ISrsServerCycle* cycle_handler) { int ret = ERROR_SUCCESS; + srs_error_t err = srs_success; // ensure the time is ok. srs_update_system_time_ms(); @@ -575,15 +576,15 @@ int SrsServer::initialize(ISrsServerCycle* cycle_handler) handler = cycle_handler; if(handler && (ret = handler->initialize()) != ERROR_SUCCESS){ - return ret; + return srs_error_new(ret, "handler initialize"); } if ((ret = http_api_mux->initialize()) != ERROR_SUCCESS) { - return ret; + return srs_error_new(ret, "http api initialize"); } if ((ret = http_server->initialize()) != ERROR_SUCCESS) { - return ret; + return srs_error_new(ret, "http server initialize"); } http_heartbeat = new SrsHttpHeartbeat(); @@ -593,7 +594,7 @@ int SrsServer::initialize(ISrsServerCycle* cycle_handler) ingester = new SrsIngester(); #endif - return ret; + return err; } int SrsServer::initialize_st() diff --git a/trunk/src/app/srs_app_server.hpp b/trunk/src/app/srs_app_server.hpp index dd8b13a8d..4b5466da5 100644 --- a/trunk/src/app/srs_app_server.hpp +++ b/trunk/src/app/srs_app_server.hpp @@ -301,7 +301,7 @@ public: * initialize server with callback handler. * @remark user must free the cycle handler. */ - virtual int initialize(ISrsServerCycle* cycle_handler); + virtual srs_error_t initialize(ISrsServerCycle* cycle_handler); virtual int initialize_st(); virtual int initialize_signal(); virtual int acquire_pid_file(); diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 1b9395b31..82b6f8a4c 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -115,4 +115,8 @@ #error "only support i386/amd64/x86_64/arm cpu" #endif +// Error predefined for all modules. +class SrsError; +typedef SrsError* srs_error_t; + #endif diff --git a/trunk/src/kernel/srs_kernel_error.cpp b/trunk/src/kernel/srs_kernel_error.cpp index 57895d88e..f552562b9 100644 --- a/trunk/src/kernel/srs_kernel_error.cpp +++ b/trunk/src/kernel/srs_kernel_error.cpp @@ -23,6 +23,12 @@ #include +#include + +#include +#include +using namespace std; + bool srs_is_system_control_error(int error_code) { return error_code == ERROR_CONTROL_RTMP_CLOSE @@ -38,3 +44,105 @@ bool srs_is_client_gracefully_close(int error_code) || error_code == ERROR_SOCKET_TIMEOUT; } +SrsError::SrsError() +{ + code = ERROR_SUCCESS; + wrapped = NULL; + cid = rerrno = line = 0; +} + +SrsError::~SrsError() +{ +} + +std::string SrsError::description() { + if (desc.empty()) { + stringstream ss; + ss << "code=" << code; + + SrsError* next = this; + while (next) { + ss << " : " << next->msg; + next = next->wrapped; + } + ss << endl; + + next = this; + while (next) { + ss << "thread #" << next->cid << ": " + << next->func << "() [" << next->file << ":" << next->line << "]" + << "[errno=" << next->rerrno << "]" + << endl; + next = next->wrapped; + } + + desc = ss.str(); + } + + return desc; +} + +SrsError* SrsError::create(const char* func, const char* file, int line, int code, const char* fmt, ...) { + int rerrno = (int)errno; + + va_list ap; + va_start(ap, fmt); + static char buffer[4096]; + vsnprintf(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + SrsError* err = new SrsError(); + + err->func = func; + err->file = file; + err->line = line; + err->code = code; + err->rerrno = rerrno; + err->msg = buffer; + err->wrapped = NULL; + if (_srs_context) { + err->cid = _srs_context->get_id(); + } + + return err; +} + +SrsError* SrsError::wrap(const char* func, const char* file, int line, SrsError* v, const char* fmt, ...) { + int rerrno = (int)errno; + + va_list ap; + va_start(ap, fmt); + static char buffer[4096]; + vsnprintf(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + SrsError* err = new SrsError(); + + err->func = func; + err->file = file; + err->line = line; + err->code = v->code; + err->rerrno = rerrno; + err->msg = buffer; + err->wrapped = v; + if (_srs_context) { + err->cid = _srs_context->get_id(); + } + + return err; +} + +SrsError* SrsError::success() { + return NULL; +} + +string SrsError::description(SrsError* err) +{ + return err? err->description() : "Success"; +} + +int SrsError::error_code(SrsError* err) +{ + return err? err->code : ERROR_SUCCESS; +} + diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index 8149f4343..f8406fcd6 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -26,6 +26,8 @@ #include +#include + // for srs-librtmp, @see https://github.com/ossrs/srs/issues/213 #ifndef _WIN32 #define ERROR_SUCCESS 0 @@ -330,19 +332,42 @@ extern bool srs_is_system_control_error(int error_code); extern bool srs_is_client_gracefully_close(int error_code); -/** - @remark: use column copy to generate the new error codes. - 01234567890 - 01234567891 - 01234567892 - 01234567893 - 01234567894 - 01234567895 - 01234567896 - 01234567897 - 01234567898 - 01234567899 - */ +// Use complex errors, @read https://github.com/ossrs/srs/issues/913 +class SrsError +{ +private: + int code; + SrsError* wrapped; + std::string msg; + + std::string func; + std::string file; + int line; + + int cid; + int rerrno; + + std::string desc; +private: + SrsError(); +public: + virtual ~SrsError(); +private: + virtual std::string description(); +public: + static SrsError* create(const char* func, const char* file, int line, int code, const char* fmt, ...); + static SrsError* wrap(const char* func, const char* file, int line, SrsError* err, const char* fmt, ...); + static SrsError* success(); + static std::string description(SrsError* err); + static int error_code(SrsError* err); +}; + +// Error helpers, should use these functions to new or wrap an error. +#define srs_success SrsError::success() +#define srs_error_new(ret, fmt, ...) SrsError::create(__FUNCTION__, __FILE__, __LINE__, ret, fmt, ##__VA_ARGS__) +#define srs_error_wrap(err, fmt, ...) SrsError::wrap(__FUNCTION__, __FILE__, __LINE__, err, fmt, ##__VA_ARGS__) +#define srs_error_desc(err) SrsError::description(err) +#define srs_error_code(err) SrsError::error_code(err) #endif diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index dbcd3eac4..14680244b 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -50,7 +50,7 @@ using namespace std; #include // pre-declare -int run(SrsServer* svr); +srs_error_t run(SrsServer* svr); int run_master(SrsServer* svr); void show_macro_features(); string srs_getenv(const char* name); @@ -182,16 +182,14 @@ int main(int argc, char** argv) 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; + srs_error_t err = run(svr); + if (err != srs_success) { + srs_error("Failed, %s", srs_error_desc(err).c_str()); } - return run(svr); + ret = srs_error_code(err); + srs_freep(err); + return ret; } /** @@ -363,11 +361,26 @@ string srs_getenv(const char* name) return ""; } -int run(SrsServer* svr) +srs_error_t run(SrsServer* svr) { + int ret = ERROR_SUCCESS; + srs_error_t err = srs_success; + + /** + * 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 ((err = svr->initialize(NULL)) != srs_success) { + return srs_error_wrap(err, "server initialize"); + } + // if not deamon, directly run master. if (!_srs_config->get_deamon()) { - return run_master(svr); + if ((ret = run_master(svr)) != ERROR_SUCCESS) { + return srs_error_new(ret, "run master"); + } + return srs_success; } srs_trace("start deamon mode..."); @@ -375,16 +388,13 @@ int run(SrsServer* svr) int pid = fork(); if(pid < 0) { - srs_error("create process error. ret=-1"); //ret=0 - return -1; + return srs_error_new(-1, "fork father process"); } // grandpa if(pid > 0) { int status = 0; - if(waitpid(pid, &status, 0) == -1) { - srs_error("wait child process error! ret=-1"); //ret=0 - } + waitpid(pid, &status, 0); srs_trace("grandpa process exit."); exit(0); } @@ -393,19 +403,22 @@ int run(SrsServer* svr) pid = fork(); if(pid < 0) { - srs_error("create process error. ret=0"); - return -1; + return srs_error_new(-1, "fork child process"); } if(pid > 0) { - srs_trace("father process exit. ret=0"); + srs_trace("father process exit"); exit(0); } // son srs_trace("son(deamon) process running."); - return run_master(svr); + if ((ret = run_master(svr)) != ERROR_SUCCESS) { + return srs_error_new(ret, "daemon run master"); + } + + return srs_success; } int run_master(SrsServer* svr)