This is an automated email from the ASF dual-hosted git repository.
jamesge pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-brpc.git
The following commit(s) were added to refs/heads/master by this push:
new c7cd158 Support fork without exec
c7cd158 is described below
commit c7cd1587365fb0eaf20cd309843cca730b280f27
Author: jamesge <[email protected]>
AuthorDate: Fri Nov 15 01:06:03 2019 -0800
Support fork without exec
---
src/bvar/detail/sampler.cpp | 76 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 58 insertions(+), 18 deletions(-)
diff --git a/src/bvar/detail/sampler.cpp b/src/bvar/detail/sampler.cpp
index 7866e76..551b716 100644
--- a/src/bvar/detail/sampler.cpp
+++ b/src/bvar/detail/sampler.cpp
@@ -57,13 +57,11 @@ struct CombineSampler {
// deletion is taken place in the thread as well.
class SamplerCollector : public bvar::Reducer<Sampler*, CombineSampler> {
public:
- SamplerCollector() : _created(false), _stop(false), _cumulated_time_us(0) {
- int rc = pthread_create(&_tid, NULL, sampling_thread, this);
- if (rc != 0) {
- LOG(FATAL) << "Fail to create sampling_thread, " << berror(rc);
- } else {
- _created = true;
- }
+ SamplerCollector()
+ : _created(false)
+ , _stop(false)
+ , _cumulated_time_us(0) {
+ create_sampling_thread();
}
~SamplerCollector() {
if (_created) {
@@ -73,33 +71,75 @@ public:
}
}
- static double get_cumulated_time(void* arg) {
- return ((SamplerCollector*)arg)->_cumulated_time_us / 1000.0 / 1000.0;
- }
-
private:
+ // Support for fork:
+ // * The singleton can be null before forking, the child callback will not
+ // be registered.
+ // * If the singleton is not null before forking, the child callback will
+ // be registered and the sampling thread will be re-created.
+ // * A forked program can be forked again.
+
+ static void child_callback_atfork() {
+
butil::get_leaky_singleton<SamplerCollector>()->after_forked_as_child();
+ }
+
+ void create_sampling_thread() {
+ const int rc = pthread_create(&_tid, NULL, sampling_thread, this);
+ if (rc != 0) {
+ LOG(FATAL) << "Fail to create sampling_thread, " << berror(rc);
+ } else {
+ _created = true;
+ pthread_atfork(NULL, NULL, child_callback_atfork);
+ }
+ }
+
+ void after_forked_as_child() {
+ _created = false;
+ create_sampling_thread();
+ }
+
void run();
-
+
static void* sampling_thread(void* arg) {
- ((SamplerCollector*)arg)->run();
+ static_cast<SamplerCollector*>(arg)->run();
return NULL;
}
+ static double get_cumulated_time(void* arg) {
+ return static_cast<SamplerCollector*>(arg)->_cumulated_time_us /
1000.0 / 1000.0;
+ }
+
private:
bool _created;
bool _stop;
+ pid_t _created_pid;
int64_t _cumulated_time_us;
pthread_t _tid;
};
+PassiveStatus<double>* g_cumulated_time_bvar = NULL;
+bvar::PerSecond<bvar::PassiveStatus<double> >* g_sampling_thread_usage_bvar =
NULL;
+
void SamplerCollector::run() {
- butil::LinkNode<Sampler> root;
- int consecutive_nosleep = 0;
#ifndef UNIT_TEST
- PassiveStatus<double> cumulated_time(get_cumulated_time, this);
- bvar::PerSecond<bvar::PassiveStatus<double> > usage(
- "bvar_sampler_collector_usage", &cumulated_time, 10);
+ // NOTE:
+ // * Following vars can't be created on thread's stack since this thread
+ // may be adandoned at any time after forking.
+ // * They can't created inside the constructor of SamplerCollector as well,
+ // which results in deadlock.
+ if (g_cumulated_time_bvar == NULL) {
+ g_cumulated_time_bvar =
+ new PassiveStatus<double>(get_cumulated_time, this);
+ }
+ if (g_sampling_thread_usage_bvar == NULL) {
+ g_sampling_thread_usage_bvar =
+ new bvar::PerSecond<bvar::PassiveStatus<double> >(
+ "bvar_sampler_collector_usage", g_cumulated_time_bvar, 10);
+ }
#endif
+
+ butil::LinkNode<Sampler> root;
+ int consecutive_nosleep = 0;
while (!_stop) {
int64_t abstime = butil::gettimeofday_us();
Sampler* s = this->reset();
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]