Skip to content

Commit 7b72595

Browse files
amiremohamadidanobi
authored andcommitted
feature: custom signal handling probe type
this commit implements a custom signal handling probe which will be triggered when the specified signal is sent to the bpftrace process. the default behavior of printing maps on `SIGUSR1` is removed. ``` bpftrace:signal:SIGUSR1 { print("hello"); } ``` Also trigger functions and extra checks for the special probes are removed as BPF_PROG_TYPE_RAW_TRACEPOINT was added in 4.17 kernel: torvalds/linux@a0fe3e5 The oldest LTS kernel still in service is 4.19, so we are free to assume BPF_PROG_TYPE_RAW_TRACEPOINT is always available
1 parent 6d36eb9 commit 7b72595

26 files changed

+252
-154
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ and this project adheres to
1818
- Add lexical/block scoping for variables
1919
- [#3367](https://github.com/bpftrace/bpftrace/pull/3367)
2020
- [Migration guide](docs/migration_guide.md#added-block-scoping-for-scratch-variables)
21+
- Replace default map printing on `SIGUSR1` with custom signal handling probes
22+
- [#3522](https://github.com/bpftrace/bpftrace/pull/3522)
23+
- [Migration guide](docs/migration_guide.md#default-sigusr1-handler-removed)
2124
#### Added
2225
- Add `--dry-run` CLI option
2326
- [#3203](https://github.com/bpftrace/bpftrace/pull/3203)

docs/migration_guide.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ BEGIN {
2828
However, the value of `$x` at the print statement was considered undefined
2929
behavior. Issue: https://github.com/bpftrace/bpftrace/issues/3017
3030

31-
Now variables are "block" scoped and the the above will throw an error at the
31+
Now variables are "block" scoped and the the above will throw an error at the
3232
print statement: "ERROR: Undefined or undeclared variable: $x".
3333

3434
If you see this error you can do multiple things to resolve it.
@@ -58,7 +58,7 @@ BEGIN {
5858
Declaring is useful for variables that hold internal bpftrace types
5959
e.g. the type returned by the `macaddr` function.
6060

61-
This is also not valid even though `$x` is set in both branches (`$x` still
61+
This is also not valid even though `$x` is set in both branches (`$x` still
6262
needs to exist in the outer scope):
6363
```
6464
BEGIN {
@@ -141,3 +141,28 @@ To mitigate such an error, just typecast `pid` or `tid` to `uint64`:
141141
Attaching 1 probe...
142142
```
143143

144+
### default `SIGUSR1` handler removed
145+
146+
https://github.com/bpftrace/bpftrace/pull/3522
147+
148+
Previously, if the bpftrace process received a `SIGUSR1` signal, it would print all maps to stdout:
149+
```
150+
# bpftrace -e 'BEGIN { @b[1] = 2; }' & kill -s USR1 $(pidof bpftrace)
151+
...
152+
@b[1]: 2
153+
```
154+
155+
This behavior is no longer supported and has been replaced with the ability
156+
to define custom handling probes:
157+
```
158+
# bpftrace -e 'self:signal:SIGUSR1 { print("hello"); }' & kill -s USR1 $(pidof bpftrace)
159+
...
160+
hello
161+
```
162+
163+
To retain the previous functionality of printing maps, you need to
164+
manually include the print statements in your signal handler probe:
165+
```
166+
# bpftrace -e 'BEGIN { @b[1] = 2; } self:signal:SIGUSR1 { print(@b); }' & kill -s USR1 $(pidof bpftrace)
167+
```
168+

man/adoc/bpftrace.adoc

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2874,6 +2874,11 @@ Most providers also support a short name which can be used instead of the full n
28742874
| Built-in events
28752875
| Kernel/User
28762876

2877+
| <<probes-self, `self`>>
2878+
| -
2879+
| Built-in events
2880+
| Kernel/User
2881+
28772882
| <<probes-hardware, `hardware`>>
28782883
| `h`
28792884
| Processor-level events
@@ -2952,6 +2957,22 @@ END {
29522957
}
29532958
----
29542959

2960+
[#probes-self]
2961+
=== self
2962+
2963+
.variants
2964+
* `self:signal:SIGUSR1`
2965+
2966+
These are special built-in events provided by the bpftrace runtime.
2967+
The trigger function is called by the bpftrace runtime when the bpftrace process receives specific events, such as a `SIGUSR1` signal.
2968+
When multiple signal handlers are attached to the same signal, only the first one is used.
2969+
2970+
----
2971+
self:signal:SIGUSR1 {
2972+
print("abc");
2973+
}
2974+
----
2975+
29552976
[#probes-hardware]
29562977
=== hardware
29572978

@@ -4087,13 +4108,6 @@ will print this on exit:
40874108
@a: 0
40884109
```
40894110

4090-
If you want to get a snapshot of your maps while the script is running, you can send the running bpftrace process a `SIGUSR1` signal. bpftrace will then print all maps to stdout. Example:
4091-
```
4092-
# bpftrace -e 'BEGIN { @b[1] = 2; }' & kill -s USR1 $(pidof bpftrace)
4093-
...
4094-
@b[1]: 2
4095-
```
4096-
40974111
=== Systemd support
40984112

40994113
To run bpftrace in the background using systemd::

src/ast/attachpoint_parser.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -276,13 +276,22 @@ AttachPointParser::State AttachPointParser::lex_attachpoint(
276276

277277
AttachPointParser::State AttachPointParser::special_parser()
278278
{
279-
// Can only have reached here if provider is `BEGIN` or `END`
280-
assert(ap_->provider == "BEGIN" || ap_->provider == "END");
281-
282-
if (parts_.size() == 2 && parts_[1] == "*")
283-
parts_.pop_back();
284-
if (parts_.size() != 1) {
285-
return argument_count_error(0);
279+
// Can only have reached here if provider is `BEGIN` or `END` or `self`
280+
assert(ap_->provider == "BEGIN" || ap_->provider == "END" ||
281+
ap_->provider == "self");
282+
283+
if (ap_->provider == "BEGIN" || ap_->provider == "END") {
284+
if (parts_.size() == 2 && parts_[1] == "*")
285+
parts_.pop_back();
286+
if (parts_.size() != 1) {
287+
return argument_count_error(0);
288+
}
289+
} else if (ap_->provider == "self") {
290+
if (parts_.size() != 3) {
291+
return argument_count_error(2);
292+
}
293+
ap_->target = parts_[1];
294+
ap_->func = parts_[2];
286295
}
287296

288297
return OK;

src/ast/passes/semantic_analyser.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3347,6 +3347,13 @@ void SemanticAnalyser::visit(AttachPoint &ap)
33473347
has_end_probe_ = true;
33483348
}
33493349
}
3350+
} else if (ap.provider == "self") {
3351+
if (ap.target == "signal") {
3352+
if (SIGNALS.find(ap.func) == SIGNALS.end())
3353+
LOG(ERROR, ap.loc, err_) << ap.func << " is not a supported signal";
3354+
return;
3355+
}
3356+
LOG(ERROR, ap.loc, err_) << ap.target << " is not a supported trigger";
33503357
} else if (ap.provider == "fentry" || ap.provider == "fexit") {
33513358
if (!bpftrace_.feature_->has_fentry()) {
33523359
LOG(ERROR, ap.loc, err_)

src/attached_probe.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,18 +148,11 @@ int AttachedProbe::detach_raw_tracepoint()
148148

149149
AttachedProbe::AttachedProbe(Probe &probe,
150150
const BpfProgram &prog,
151-
bool safe_mode,
152151
BPFtrace &bpftrace)
153152
: probe_(probe), progfd_(prog.fd()), bpftrace_(bpftrace)
154153
{
155154
LOG(V1) << "Attaching " << probe_.orig_name;
156155
switch (probe_.type) {
157-
case ProbeType::special:
158-
// If BPF_PROG_TYPE_RAW_TRACEPOINT is available, no need to attach prog
159-
// to anything -- we will simply BPF_PROG_RUN it
160-
if (!bpftrace_.feature_->has_raw_tp_special())
161-
attach_uprobe(getpid(), safe_mode);
162-
break;
163156
case ProbeType::kprobe:
164157
attach_kprobe();
165158
break;
@@ -312,7 +305,6 @@ std::string AttachedProbe::eventname() const
312305
offset_str << std::hex << offset_;
313306
return eventprefix() + sanitise_bpf_program_name(probe_.attach_point) +
314307
"_" + offset_str.str() + index_str;
315-
case ProbeType::special:
316308
case ProbeType::uprobe:
317309
case ProbeType::uretprobe:
318310
case ProbeType::usdt:

src/attached_probe.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@ std::string progtypeName(libbpf::bpf_prog_type t);
2222

2323
class AttachedProbe {
2424
public:
25-
AttachedProbe(Probe &probe,
26-
const BpfProgram &prog,
27-
bool safe_mode,
28-
BPFtrace &bpftrace);
25+
AttachedProbe(Probe &probe, const BpfProgram &prog, BPFtrace &bpftrace);
2926
AttachedProbe(Probe &probe,
3027
const BpfProgram &prog,
3128
int pid,

src/bpfbytecode.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,11 @@ void BpfBytecode::load_progs(const RequiredResources &resources,
186186
bpf_program__set_log_buf(prog.bpf_prog(), log_buf.data(), log_buf.size());
187187
}
188188

189+
std::vector<Probe> special_probes;
190+
for (auto probe : resources.special_probes)
191+
special_probes.push_back(probe.second);
192+
prepare_progs(special_probes, btf, feature, config);
189193
prepare_progs(resources.probes, btf, feature, config);
190-
prepare_progs(resources.special_probes, btf, feature, config);
191194
prepare_progs(resources.watchpoint_probes, btf, feature, config);
192195

193196
int res = bpf_object__load(bpf_object_.get());
@@ -264,7 +267,7 @@ void BpfBytecode::prepare_progs(const std::vector<Probe> &probes,
264267
{
265268
for (auto &probe : probes) {
266269
auto &program = getProgramForProbe(probe);
267-
program.set_prog_type(probe, feature);
270+
program.set_prog_type(probe);
268271
program.set_expected_attach_type(probe, feature);
269272
program.set_attach_target(probe, btf, config);
270273
program.set_no_autoattach();

src/bpffeature.cpp

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -564,32 +564,6 @@ bool BPFfeature::has_skb_output()
564564
return *has_skb_output_;
565565
}
566566

567-
bool BPFfeature::has_raw_tp_special()
568-
{
569-
if (has_raw_tp_special_.has_value())
570-
return *has_raw_tp_special_;
571-
572-
struct bpf_insn insns[] = { BPF_MOV64_IMM(BPF_REG_0, 0), BPF_EXIT_INSN() };
573-
int fd;
574-
575-
// Check that we can both load BPF_PROG_TYPE_RAW_TRACEPOINT and that
576-
// BPF_PROG_RUN is supported by the kernel
577-
if (try_load(libbpf::BPF_PROG_TYPE_RAW_TRACEPOINT,
578-
insns,
579-
ARRAY_SIZE(insns),
580-
nullptr,
581-
std::nullopt,
582-
&fd)) {
583-
struct bpf_test_run_opts opts = {};
584-
opts.sz = sizeof(opts);
585-
has_raw_tp_special_ = !::bpf_prog_test_run_opts(fd, &opts);
586-
close(fd);
587-
} else
588-
has_raw_tp_special_ = false;
589-
590-
return *has_raw_tp_special_;
591-
}
592-
593567
std::string BPFfeature::report()
594568
{
595569
std::stringstream buf;
@@ -643,7 +617,6 @@ std::string BPFfeature::report()
643617
<< " fentry: " << to_str(has_fentry())
644618
<< " kprobe_multi: " << to_str(has_kprobe_multi())
645619
<< " uprobe_multi: " << to_str(has_uprobe_multi())
646-
<< " raw_tp_special: " << to_str(has_raw_tp_special())
647620
<< " iter: " << to_str(has_iter("task")) << std::endl;
648621

649622
return buf.str();

src/bpffeature.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ class BPFfeature {
9999
bool has_uprobe_multi();
100100
bool has_fentry();
101101
bool has_skb_output();
102-
bool has_raw_tp_special();
103102
bool has_prog_fentry();
104103
bool has_module_btf();
105104
bool has_iter(std::string name);
@@ -143,7 +142,6 @@ class BPFfeature {
143142
std::optional<bool> has_kprobe_multi_;
144143
std::optional<bool> has_uprobe_multi_;
145144
std::optional<bool> has_skb_output_;
146-
std::optional<bool> has_raw_tp_special_;
147145
std::optional<bool> has_prog_fentry_;
148146
std::optional<bool> has_module_btf_;
149147
std::optional<bool> has_btf_func_global_;

0 commit comments

Comments
 (0)