forked from apache/brpc
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtask_tracer.h
More file actions
130 lines (104 loc) · 3.96 KB
/
task_tracer.h
File metadata and controls
130 lines (104 loc) · 3.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
#ifndef BTHREAD_TASK_TRACER_H
#define BTHREAD_TASK_TRACER_H
#ifdef BRPC_BTHREAD_TRACER
#include <signal.h>
#include <vector>
#include <libunwind.h>
#include "butil/synchronization/condition_variable.h"
#include "butil/intrusive_ptr.hpp"
#include "butil/strings/safe_sprintf.h"
#include "butil/shared_object.h"
#include "bthread/task_meta.h"
#include "bthread/mutex.h"
namespace bthread {
// Tracer for bthread.
class TaskTracer {
public:
// Returns 0 on success, -1 otherwise.
bool Init();
// Set the status to `s'.
void set_status(TaskStatus s, TaskMeta* meta);
static void set_running_status(pid_t worker_tid, TaskMeta* meta);
static bool set_end_status_unsafe(TaskMeta* m);
// Trace the bthread of `tid'.
std::string Trace(bthread_t tid);
void Trace(std::ostream& os, bthread_t tid);
// When the worker is jumping stack from a bthread to another,
void WaitForTracing(TaskMeta* m);
private:
// Error number guard used in signal handler.
class ErrnoGuard {
public:
ErrnoGuard() : _errno(errno) {}
~ErrnoGuard() { errno = _errno; }
private:
int _errno;
};
struct Result {
template<typename... Args>
static Result MakeErrorResult(const char* fmt, Args&&... args) {
Result result;
result.SetError(fmt, std::forward<Args>(args)...);
return result;
}
template<typename... Args>
void SetError(const char* fmt, Args&&... args) {
error = true;
butil::ignore_result(butil::strings::SafeSPrintf(
err_msg, fmt, std::forward<Args>(args)...));
}
std::string OutputToString() const;
void OutputToStream(std::ostream& os) const;
static constexpr size_t MAX_TRACE_NUM = 64;
void* ips[MAX_TRACE_NUM];
size_t frame_count{0};
char err_msg[64];
bool error{false};
};
// For signal trace.
struct SignalSync : public butil::SharedObject {
~SignalSync() override;
bool Init();
int pipe_fds[2]{-1, -1};
Result result;
};
static TaskStatus WaitForJumping(TaskMeta* m);
Result TraceImpl(bthread_t tid);
unw_cursor_t MakeCursor(bthread_fcontext_t fcontext);
Result ContextTrace(bthread_fcontext_t fcontext);
static Result TraceByLibunwind(unw_cursor_t& cursor);
static bool RegisterSignalHandler();
static void SignalHandler(int sig, siginfo_t* info, void* context);
Result SignalTrace(pid_t worker_tid);
// Make sure only one bthread is traced at a time.
Mutex _trace_request_mutex;
// For signal trace.
// Make sure bthread does not jump stack when it is being traced.
butil::Mutex _mutex;
butil::ConditionVariable _cond{&_mutex};
// For context trace.
unw_context_t _context{};
// Hold SignalSync and wait until no one is using it before releasing it.
// This will avoid deadlock because it will not be released in the signal handler.
std::vector<butil::intrusive_ptr<SignalSync>> _inuse_signal_syncs;
bvar::LatencyRecorder _trace_time{"bthread_trace_time"};
};
} // namespace bthread
#endif // BRPC_BTHREAD_TRACER
#endif // BRPC_BTHREAD_TRACER_H