diff --git a/trunk/auto/auto_headers.sh b/trunk/auto/auto_headers.sh
index 1998a9374..82d77186d 100755
--- a/trunk/auto/auto_headers.sh
+++ b/trunk/auto/auto_headers.sh
@@ -171,6 +171,11 @@ if [ $SRS_SANITIZER_LOG == YES ]; then
else
srs_undefine_macro "SRS_SANITIZER_LOG" $SRS_AUTO_HEADERS_H
fi
+if [ $SRS_VALGRIND == YES ]; then
+ srs_define_macro "SRS_VALGRIND" $SRS_AUTO_HEADERS_H
+else
+ srs_undefine_macro "SRS_VALGRIND" $SRS_AUTO_HEADERS_H
+fi
#####################################################################################
# for embeded.
diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md
index 2aedae016..5d6b42374 100644
--- a/trunk/doc/CHANGELOG.md
+++ b/trunk/doc/CHANGELOG.md
@@ -7,6 +7,7 @@ The changelog for SRS.
## SRS 6.0 Changelog
+* v6.0, 2024-08-21, Merge [#4150](https://github.com/ossrs/srs/pull/4150): API: Support new HTTP API for VALGRIND. v6.0.149 (#4150)
* v6.0, 2024-08-15, Merge [#4144](https://github.com/ossrs/srs/pull/4144): HTTP-FLV: Crash when multiple viewers. v6.0.148 (#4144)
* v6.0, 2024-08-15, Merge [#4142](https://github.com/ossrs/srs/pull/4142): Config: Add more utest for env config. v6.0.147 (#4142)
* v6.0, 2024-08-14, Merge [#4141](https://github.com/ossrs/srs/pull/4141): Live: Crash for invalid live stream state when unmount HTTP. v6.0.146 (#4141)
diff --git a/trunk/src/app/srs_app_gb28181.hpp b/trunk/src/app/srs_app_gb28181.hpp
index be6250948..3ac91a3da 100644
--- a/trunk/src/app/srs_app_gb28181.hpp
+++ b/trunk/src/app/srs_app_gb28181.hpp
@@ -188,7 +188,7 @@ public:
void on_media_transport(SrsSharedResource media);
// Get the candidate for SDP generation, the public IP address for device to connect to.
std::string pip();
-// Interface ISrsOneCycleThreadHandler
+// Interface ISrsCoroutineHandler
public:
virtual srs_error_t cycle();
private:
@@ -305,7 +305,7 @@ private:
public:
virtual const SrsContextId& get_id();
virtual std::string desc();
-// Interface ISrsOneCycleThreadHandler
+// Interface ISrsCoroutineHandler
public:
virtual srs_error_t cycle();
private:
@@ -333,7 +333,7 @@ public:
// Interface ISrsStartable
public:
virtual srs_error_t start();
-// Interface ISrsOneCycleThreadHandler
+// Interface ISrsCoroutineHandler
public:
virtual srs_error_t cycle();
private:
@@ -362,7 +362,7 @@ public:
// Interface ISrsStartable
public:
virtual srs_error_t start();
-// Interface ISrsOneCycleThreadHandler
+// Interface ISrsCoroutineHandler
public:
virtual srs_error_t cycle();
private:
@@ -422,7 +422,7 @@ public:
public:
virtual const SrsContextId& get_id();
virtual std::string desc();
-// Interface ISrsOneCycleThreadHandler
+// Interface ISrsCoroutineHandler
public:
virtual srs_error_t cycle();
private:
diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp
index c8bc71010..b1bd339a4 100644
--- a/trunk/src/app/srs_app_http_api.cpp
+++ b/trunk/src/app/srs_app_http_api.cpp
@@ -31,6 +31,11 @@ using namespace std;
#include
#include
+#ifdef SRS_VALGRIND
+#include
+#include
+#endif
+
#if defined(__linux__) || defined(SRS_OSX)
#include
#endif
@@ -267,6 +272,7 @@ srs_error_t SrsGoApiV1::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r
urls->set("clusters", SrsJsonAny::str("origin cluster server API"));
urls->set("perf", SrsJsonAny::str("System performance stat"));
urls->set("tcmalloc", SrsJsonAny::str("tcmalloc api with params ?page=summary|api"));
+ urls->set("valgrind", SrsJsonAny::str("valgrind api with params ?check=full|added|changed|new|quick"));
SrsJsonObject* tests = SrsJsonAny::object();
obj->set("tests", tests);
@@ -1090,6 +1096,100 @@ srs_error_t SrsGoApiTcmalloc::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess
}
#endif
+#ifdef SRS_VALGRIND
+
+SrsGoApiValgrind::SrsGoApiValgrind()
+{
+ trd_ = NULL;
+}
+
+SrsGoApiValgrind::~SrsGoApiValgrind()
+{
+ srs_freep(trd_);
+}
+
+srs_error_t SrsGoApiValgrind::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
+{
+ srs_error_t err = srs_success;
+
+ if (!trd_) {
+ trd_ = new SrsSTCoroutine("valgrind", this, _srs_context->get_id());
+ if ((err = trd_->start()) != srs_success) {
+ return srs_error_wrap(err, "start");
+ }
+ }
+
+ string check = r->query_get("check");
+ srs_trace("query check=%s", check.c_str());
+
+ // Must be full|added|changed|new|quick, set to full for other values.
+ if (check != "full" && check != "added" && check != "changed" && check != "new" && check != "quick") {
+ srs_warn("force set check=%s to full", check.c_str());
+ check = "full";
+ }
+
+ // By default, response the json style response.
+ SrsUniquePtr obj(SrsJsonAny::object());
+
+ obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS));
+
+ SrsJsonObject* res = SrsJsonAny::object();
+ res->set("check", SrsJsonAny::str(check.c_str()));
+ res->set("help", SrsJsonAny::str("?check=full|added|changed|new|quick"));
+ res->set("see", SrsJsonAny::str("https://valgrind.org/docs/manual/mc-manual.html"));
+ obj->set("data", res);
+
+ // Does a memory check later.
+ if (check == "full") {
+ res->set("call", SrsJsonAny::str("VALGRIND_DO_LEAK_CHECK"));
+ } else if (check == "quick") {
+ res->set("call", SrsJsonAny::str("VALGRIND_DO_QUICK_LEAK_CHECK"));
+ } else if (check == "added") {
+ res->set("call", SrsJsonAny::str("VALGRIND_DO_ADDED_LEAK_CHECK"));
+ } else if (check == "changed") {
+ res->set("call", SrsJsonAny::str("VALGRIND_DO_CHANGED_LEAK_CHECK"));
+ } else if (check == "new") {
+ res->set("call", SrsJsonAny::str("VALGRIND_DO_NEW_LEAK_CHECK"));
+ }
+ task_ = check;
+
+ return srs_api_response(w, r, obj->dumps());
+}
+
+srs_error_t SrsGoApiValgrind::cycle()
+{
+ srs_error_t err = srs_success;
+
+ while (true) {
+ if ((err = trd_->pull()) != srs_success) {
+ return srs_error_wrap(err, "pull");
+ }
+
+ std::string check = task_;
+ task_ = "";
+
+ if (!check.empty()) {
+ srs_trace("do memory check=%s", check.c_str());
+ }
+
+ if (check == "full") {
+ VALGRIND_DO_LEAK_CHECK;
+ } else if (check == "quick") {
+ VALGRIND_DO_QUICK_LEAK_CHECK;
+ } else if (check == "added") {
+ VALGRIND_DO_ADDED_LEAK_CHECK;
+ } else if (check == "changed") {
+ VALGRIND_DO_CHANGED_LEAK_CHECK;
+ } else if (check == "new") {
+ VALGRIND_DO_NEW_LEAK_CHECK;
+ }
+
+ srs_usleep(3 * SRS_UTIME_SECONDS);
+ }
+
+ return err;
+}
+#endif
SrsGoApiMetrics::SrsGoApiMetrics()
{
diff --git a/trunk/src/app/srs_app_http_api.hpp b/trunk/src/app/srs_app_http_api.hpp
index 8bcb30e50..8789d42e9 100644
--- a/trunk/src/app/srs_app_http_api.hpp
+++ b/trunk/src/app/srs_app_http_api.hpp
@@ -216,6 +216,23 @@ public:
};
#endif
+#ifdef SRS_VALGRIND
+class SrsGoApiValgrind : public ISrsHttpHandler, public ISrsCoroutineHandler
+{
+private:
+ SrsCoroutine* trd_;
+ std::string task_;
+public:
+ SrsGoApiValgrind();
+ virtual ~SrsGoApiValgrind();
+public:
+ virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
+// Interface ISrsCoroutineHandler
+public:
+ virtual srs_error_t cycle();
+};
+#endif
+
class SrsGoApiMetrics : public ISrsHttpHandler
{
private:
diff --git a/trunk/src/app/srs_app_http_conn.hpp b/trunk/src/app/srs_app_http_conn.hpp
index 57f984a49..9d1cc1055 100644
--- a/trunk/src/app/srs_app_http_conn.hpp
+++ b/trunk/src/app/srs_app_http_conn.hpp
@@ -94,7 +94,7 @@ public:
// Interface ISrsStartable
public:
virtual srs_error_t start();
-// Interface ISrsOneCycleThreadHandler
+// Interface ISrsCoroutineHandler
public:
virtual srs_error_t cycle();
private:
diff --git a/trunk/src/app/srs_app_recv_thread.hpp b/trunk/src/app/srs_app_recv_thread.hpp
index 5fa011db5..7d29a4b39 100644
--- a/trunk/src/app/srs_app_recv_thread.hpp
+++ b/trunk/src/app/srs_app_recv_thread.hpp
@@ -204,7 +204,7 @@ public:
virtual srs_error_t start();
public:
virtual srs_error_t pull();
-// Interface ISrsOneCycleThreadHandler
+// Interface ISrsCoroutineHandler
public:
virtual srs_error_t cycle();
};
diff --git a/trunk/src/app/srs_app_rtmp_conn.hpp b/trunk/src/app/srs_app_rtmp_conn.hpp
index 8c86627fe..9a772ffb7 100644
--- a/trunk/src/app/srs_app_rtmp_conn.hpp
+++ b/trunk/src/app/srs_app_rtmp_conn.hpp
@@ -181,7 +181,7 @@ public:
// when client cycle thread stop, invoke the on_thread_stop(), which will use server
// To remove the client by server->remove(this).
virtual srs_error_t start();
-// Interface ISrsOneCycleThreadHandler
+// Interface ISrsCoroutineHandler
public:
// The thread cycle function,
// when serve connection completed, terminate the loop which will terminate the thread,
diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp
index aff62f02e..16bc99e8c 100644
--- a/trunk/src/app/srs_app_server.cpp
+++ b/trunk/src/app/srs_app_server.cpp
@@ -773,9 +773,17 @@ srs_error_t SrsServer::http_handle()
// The test api for get tcmalloc stats.
// @see Memory Introspection in https://gperftools.github.io/gperftools/tcmalloc.html
if ((err = http_api_mux->handle("/api/v1/tcmalloc", new SrsGoApiTcmalloc())) != srs_success) {
- return srs_error_wrap(err, "handle tests errors");
+ return srs_error_wrap(err, "handle tcmalloc errors");
}
#endif
+
+#ifdef SRS_VALGRIND
+ // The test api for valgrind. See VALGRIND_DO_LEAK_CHECK in https://valgrind.org/docs/manual/mc-manual.html
+ if ((err = http_api_mux->handle("/api/v1/valgrind", new SrsGoApiValgrind())) != srs_success) {
+ return srs_error_wrap(err, "handle valgrind errors");
+ }
+#endif
+
// metrics by prometheus
if ((err = http_api_mux->handle("/metrics", new SrsGoApiMetrics())) != srs_success) {
return srs_error_wrap(err, "handle tests errors");
diff --git a/trunk/src/app/srs_app_st.hpp b/trunk/src/app/srs_app_st.hpp
index d7315b20c..11f2c2195 100644
--- a/trunk/src/app/srs_app_st.hpp
+++ b/trunk/src/app/srs_app_st.hpp
@@ -291,7 +291,7 @@ public:
public:
virtual const SrsContextId& cid();
virtual void set_cid(const SrsContextId& cid);
-// Interface ISrsOneCycleThreadHandler
+// Interface ISrsCoroutineHandler
public:
virtual srs_error_t cycle();
// Interface ISrsResource
diff --git a/trunk/src/core/srs_core_version6.hpp b/trunk/src/core/srs_core_version6.hpp
index 33a00d8c9..9e3f4b4a1 100644
--- a/trunk/src/core/srs_core_version6.hpp
+++ b/trunk/src/core/srs_core_version6.hpp
@@ -9,6 +9,6 @@
#define VERSION_MAJOR 6
#define VERSION_MINOR 0
-#define VERSION_REVISION 148
+#define VERSION_REVISION 149
#endif