Skip to content

Commit

Permalink
Some fix and change on curl adaptor and photon thread alloc/dealloc h…
Browse files Browse the repository at this point in the history
…ook (#154)

* Fix curl destruct order; add url unescape.
* photon thread alloc using static object

Signed-off-by: Coldwings <coldwings@me.com>
  • Loading branch information
Coldwings authored Jul 7, 2023
1 parent a73a22c commit d334372
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 29 deletions.
8 changes: 4 additions & 4 deletions common/callback.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ struct Delegate : public Delegate_Base
template<typename U> // Function with U* as the 1st argument
using UFunc = R (*)(U*, Ts...);

Delegate(void* obj, Func func) { bind(obj, func); }
Delegate(Func func, void* obj) { bind(obj, func); }
Delegate(Func0 func0) { bind(func0); }
constexpr Delegate(void* obj, Func func) : _obj(obj), _func(func) {}
constexpr Delegate(Func func, void* obj) : _obj(obj), _func(func) {}
constexpr Delegate(Func0 func0) : _obj(nullptr), _func((Func&)func0) {}

template<typename U>
Delegate(U* obj, UFunc<U> func) { bind(obj, func); }
constexpr Delegate(U* obj, UFunc<U> func) : _obj(obj), _func((Func&)func) {}

template<typename U>
Delegate(U* obj, UMFunc<U> func) { bind(obj, func); }
Expand Down
12 changes: 9 additions & 3 deletions net/curl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ static uint64_t on_timer(void* = nullptr) {
}
/* CURLMOPT_TIMERFUNCTION */
static int timer_cb(CURLM*, long timeout_ms, void*) {
if (timeout_ms >= 0) {
if (timeout_ms >= 0 && cctx.g_timer) {
cctx.g_timer->reset(timeout_ms * 1000UL);
}
return 0;
Expand Down Expand Up @@ -244,11 +244,11 @@ int libcurl_init(long flags, long pipelining, long maxconn) {
return 0;
}
void libcurl_fini() {
delete cctx.g_timer;
cctx.g_timer = nullptr;
cctx.g_loop->stop();
delete cctx.g_loop;
cctx.g_loop = nullptr;
delete cctx.g_timer;
cctx.g_timer = nullptr;
delete cctx.g_poller;
cctx.g_poller = nullptr;
CURLMcode ret = curl_multi_cleanup(cctx.g_libcurl_multi);
Expand All @@ -262,5 +262,11 @@ std::string url_escape(const char* str) {
DEFER(curl_free(s));
return std::string(s);
}

std::string url_unescape(const char* str) {
auto s = curl_unescape(str, 0);
DEFER(curl_free(s));
return std::string(s);
}
} // namespace net
}
40 changes: 39 additions & 1 deletion net/curl.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ int curl_perform(CURL* curl, uint64_t timeout);
void libcurl_fini();

std::string url_escape(const char*);
std::string url_unescape(const char*);

inline void convert(const std::string& v, uint64_t& value) {
value = std::atoll(v.c_str());
Expand Down Expand Up @@ -291,6 +292,12 @@ class cURL {
return setopt(CURLOPT_FOLLOWLOCATION, v),
setopt(CURLOPT_MAXREDIRS, max_redir);
}
cURL& set_proxy(const char* proxy) {
return setopt(CURLOPT_PROXY, proxy);
}
cURL& set_noproxy(const char* proxy) {
return setopt(CURLOPT_NOPROXY, proxy);
}
template <typename T>
cURL& set_header_container(T* stream) {
return setopt(CURLOPT_HEADERDATA, (void*)stream),
Expand Down Expand Up @@ -332,6 +339,9 @@ class cURL {
setopt(CURLOPT_HTTPGET, 1L);
setopt(CURLOPT_URL, url);
setopt(CURLOPT_HTTPHEADER, headers.list);
#if LIBCURL_VERSION_MAJOR > 7 || LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 37
setopt(CURLOPT_PROXYHEADER, proxy_headers.list);
#endif
set_write_stream(stream);
ret = (CURLcode)net::curl_perform(m_curl, timeout);
return get_response_code();
Expand All @@ -341,6 +351,9 @@ class cURL {
setopt(CURLOPT_HTTPGET, 1L);
setopt(CURLOPT_URL, url);
setopt(CURLOPT_HTTPHEADER, headers.list);
#if LIBCURL_VERSION_MAJOR > 7 || LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 37
setopt(CURLOPT_PROXYHEADER, proxy_headers.list);
#endif
ret = (CURLcode)net::curl_perform(m_curl, timeout);
return get_response_code();
}
Expand All @@ -350,6 +363,9 @@ class cURL {
setopt(CURLOPT_URL, url);
setopt(CURLOPT_CUSTOMREQUEST, "HEAD");
setopt(CURLOPT_HTTPHEADER, headers.list);
#if LIBCURL_VERSION_MAJOR > 7 || LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 37
setopt(CURLOPT_PROXYHEADER, proxy_headers.list);
#endif
set_write_stream(stream);
ret = (CURLcode)net::curl_perform(m_curl, timeout);
return get_response_code();
Expand All @@ -370,6 +386,9 @@ class cURL {
long POST(const char* url, const char* post_fields, W* wstream,
uint64_t timeout = -1) {
setopt(CURLOPT_HTTPHEADER, headers.list);
#if LIBCURL_VERSION_MAJOR > 7 || LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 37
setopt(CURLOPT_PROXYHEADER, proxy_headers.list);
#endif
setopt(CURLOPT_POSTFIELDS, post_fields);
return POST(url, wstream, timeout);
}
Expand All @@ -380,6 +399,9 @@ class cURL {
setopt(CURLOPT_URL, url);
setopt(CURLOPT_POST, 1L);
setopt(CURLOPT_HTTPHEADER, headers.list);
#if LIBCURL_VERSION_MAJOR > 7 || LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 37
setopt(CURLOPT_PROXYHEADER, proxy_headers.list);
#endif
ret = (CURLcode)net::curl_perform(m_curl, timeout);
return get_response_code();
}
Expand All @@ -392,6 +414,9 @@ class cURL {
setopt(CURLOPT_PUT, 1L);
setopt(CURLOPT_URL, url);
setopt(CURLOPT_HTTPHEADER, headers.list);
#if LIBCURL_VERSION_MAJOR > 7 || LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 37
setopt(CURLOPT_PROXYHEADER, proxy_headers.list);
#endif
// setopt(CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
ret = (CURLcode)net::curl_perform(m_curl, timeout);
return get_response_code();
Expand All @@ -400,6 +425,9 @@ class cURL {
setopt(CURLOPT_URL, url);
setopt(CURLOPT_CUSTOMREQUEST, "DELETE");
setopt(CURLOPT_HTTPHEADER, headers.list);
#if LIBCURL_VERSION_MAJOR > 7 || LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 37
setopt(CURLOPT_PROXYHEADER, proxy_headers.list);
#endif
ret = (CURLcode)net::curl_perform(m_curl, timeout);
return get_response_code();
}
Expand All @@ -421,6 +449,16 @@ class cURL {
return *this;
}

cURL& append_proxy_header(const std::string& key, const std::string& val) {
proxy_headers.append(key + std::string(": ") + val);
return *this;
}

cURL& clear_proxy_header() {
proxy_headers.clear();
return *this;
}

struct slist {
struct curl_slist* list = nullptr;
slist() = default;
Expand All @@ -447,7 +485,7 @@ class cURL {
CURL* m_curl;
char m_errmsg[CURL_ERROR_SIZE];
CURLcode ret = CURLE_OK;
slist headers;
slist headers, proxy_headers;
template <typename T>
cURL& _setopt(CURLoption option, T arg) {
if (ret != CURLE_OK) return *this;
Expand Down
6 changes: 5 additions & 1 deletion thread/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,8 @@ add_test(NAME test-tls-order-native COMMAND $<TARGET_FILE:test-tls-order-native>

add_executable(test-tls-order-photon test-tls-order-photon.cpp)
target_link_libraries(test-tls-order-photon PRIVATE photon_shared ${testing_libs})
add_test(NAME test-tls-order-photon COMMAND $<TARGET_FILE:test-tls-order-photon>)
add_test(NAME test-tls-order-photon COMMAND $<TARGET_FILE:test-tls-order-photon>)

add_executable(test-lib-data test-lib-data.cpp)
target_link_libraries(test-lib-data PRIVATE photon_shared ${testing_libs})
add_test(NAME test-lib-data COMMAND $<TARGET_FILE:test-lib-data>)
89 changes: 89 additions & 0 deletions thread/test/test-lib-data.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
Copyright 2022 The Photon Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <gtest/gtest.h>
#include <libgen.h>
#include <photon/common/utility.h>
#include <photon/photon.h>
#include <stdio.h>
#include <stdlib.h>

bool popen_test(const std::string& cmd, int expect = 0) {
puts(cmd.c_str());
auto p = popen(cmd.c_str(), "r");
char buffer[4096];
while (fgets(buffer, sizeof(buffer), p) != NULL)
;
auto r = pclose(p);
if (WIFEXITED(r)) return WEXITSTATUS(r) == expect;
puts("Not exit");
return false;
}

std::string popen_read(const std::string& cmd, int expect = 0) {
std::string ret;
puts(cmd.c_str());
auto p = popen(cmd.c_str(), "r");
char buffer[4096];
while (fgets(buffer, sizeof(buffer), p) != NULL) {
ret += buffer;
puts(buffer);
}
pclose(p);
return ret;
}

std::string libpath(uint64_t pid) {
auto path =
popen_read("cat /proc/" + std::to_string(pid) +
"/maps | grep libphoton | tr -s ' ' | cut -f 6 -d ' '"
" | head -n 1");
EXPECT_FALSE(path.empty());
char* tp = strdup(path.c_str());
path = dirname(tp);
puts(path.c_str());
free(tp);
return path;
}

TEST(static_lib, photon_thread_alloc) {
#ifdef __linux__
auto pid = getpid();
auto p = libpath(pid) + "/libphoton.a";
EXPECT_TRUE(popen_test("objdump -tr \"" + p +
"\" | grep photon_thread_allocE | grep .data"));
EXPECT_TRUE(popen_test("objdump -tr \"" + p +
"\" | grep photon_thread_deallocE | grep .data"));
#endif
}

TEST(shared_lib, photon_thread_alloc) {
#ifdef __linux__
auto pid = getpid();
auto p = libpath(pid) + "/libphoton.so";
EXPECT_TRUE(popen_test("objdump -tr \"" + p +
"\" | grep photon_thread_allocE | grep .data"));
EXPECT_TRUE(popen_test("objdump -tr \"" + p +
"\" | grep photon_thread_deallocE | grep .data"));
#endif
}

int main(int argc, char** argv) {
photon::init(photon::INIT_EVENT_NONE, 0);
DEFER(photon::fini());
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
33 changes: 13 additions & 20 deletions thread/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,17 +130,10 @@ namespace photon
free(ptr);
}

Delegate<void *, size_t> &photon_thread_alloc() {
static Delegate<void *, size_t> _photon_thread_alloc(
&default_photon_thread_stack_alloc, nullptr);
return _photon_thread_alloc;
}

Delegate<void, void *, size_t> &photon_thread_dealloc() {
static Delegate<void, void *, size_t> _photon_thread_dealloc(
&default_photon_thread_stack_dealloc, nullptr);
return _photon_thread_dealloc;
}
static Delegate<void*, size_t> photon_thread_alloc(
&default_photon_thread_stack_alloc, nullptr);
static Delegate<void, void*, size_t> photon_thread_dealloc(
&default_photon_thread_stack_dealloc, nullptr);

struct vcpu_t;
struct thread;
Expand Down Expand Up @@ -290,7 +283,7 @@ namespace photon
assert(state == states::DONE);
// `buf` and `stack_size` will always store on register
// when calling deallocating.
photon_thread_dealloc()(buf, stack_size);
photon_thread_dealloc(buf, stack_size);
}
};

Expand Down Expand Up @@ -845,7 +838,7 @@ R"(
LOG_ERROR_RETURN(ENOSYS, nullptr, "Photon not initialized in this vCPU (OS thread)");
size_t randomizer = (rand() % 32) * (1024 + 8);
stack_size = align_up(randomizer + stack_size + sizeof(thread), PAGE_SIZE);
char *ptr = (char *)photon_thread_alloc()(stack_size);
char* ptr = (char*)photon_thread_alloc(stack_size);
auto p = ptr + stack_size - sizeof(thread) - randomizer;
(uint64_t&)p &= ~63;
auto th = new (p) thread;
Expand Down Expand Up @@ -1815,18 +1808,18 @@ R"(
return --_n_vcpu;
}

void set_photon_thread_stack_allocator(
Delegate<void *, size_t> _photon_thread_alloc,
Delegate<void, void *, size_t> _photon_thread_dealloc) {
photon_thread_alloc() = _photon_thread_alloc;
photon_thread_dealloc() = _photon_thread_dealloc;
}

void* stackful_malloc(size_t size) {
return CURRENT->stackful_malloc(size);
}

void stackful_free(void* ptr) {
CURRENT->stackful_free(ptr);
}

void set_photon_thread_stack_allocator(
Delegate<void *, size_t> _photon_thread_alloc,
Delegate<void, void *, size_t> _photon_thread_dealloc) {
photon_thread_alloc = _photon_thread_alloc;
photon_thread_dealloc = _photon_thread_dealloc;
}
}

0 comments on commit d334372

Please sign in to comment.