1 // Functions for handling event triggers.
2 #include "config.h"  // IWYU pragma: keep
3 
4 #include "event.h"
5 
6 #include <signal.h>
7 #include <stddef.h>
8 #include <unistd.h>
9 
10 #include <algorithm>
11 #include <atomic>
12 #include <functional>
13 #include <memory>
14 #include <string>
15 #include <type_traits>
16 
17 #include "common.h"
18 #include "fallback.h"  // IWYU pragma: keep
19 #include "input_common.h"
20 #include "io.h"
21 #include "parser.h"
22 #include "proc.h"
23 #include "signal.h"
24 #include "termsize.h"
25 #include "wcstringutil.h"
26 #include "wutil.h"  // IWYU pragma: keep
27 
28 class pending_signals_t {
29     static constexpr size_t SIGNAL_COUNT = NSIG;
30 
31     /// A counter that is incremented each time a pending signal is received.
32     std::atomic<uint32_t> counter_{0};
33 
34     /// List of pending signals.
35     std::array<std::atomic<bool>, SIGNAL_COUNT> received_{};
36 
37     /// The last counter visible in acquire_pending().
38     /// This is not accessed from a signal handler.
39     owning_lock<uint32_t> last_counter_{0};
40 
41    public:
42     pending_signals_t() = default;
43 
44     /// No copying.
45     pending_signals_t(const pending_signals_t &);
46     void operator=(const pending_signals_t &);
47 
48     /// Mark a signal as pending. This may be called from a signal handler.
49     /// We expect only one signal handler to execute at once.
50     /// Also note that these may be coalesced.
mark(int which)51     void mark(int which) {
52         if (which >= 0 && static_cast<size_t>(which) < received_.size()) {
53             // Must mark our received first, then pending.
54             received_[which].store(true, std::memory_order_relaxed);
55             uint32_t count = counter_.load(std::memory_order_relaxed);
56             counter_.store(1 + count, std::memory_order_release);
57         }
58     }
59 
60     /// \return the list of signals that were set, clearing them.
acquire_pending()61     std::bitset<SIGNAL_COUNT> acquire_pending() {
62         auto current = last_counter_.acquire();
63 
64         // Check the counter first. If it hasn't changed, no signals have been received.
65         uint32_t count = counter_.load(std::memory_order_acquire);
66         if (count == *current) {
67             return {};
68         }
69 
70         // The signal count has changed. Store the new counter and fetch all the signals that are
71         // set.
72         *current = count;
73         std::bitset<SIGNAL_COUNT> result{};
74         uint32_t bit = 0;
75         for (auto &signal : received_) {
76             bool val = signal.load(std::memory_order_relaxed);
77             if (val) {
78                 result.set(bit);
79                 signal.store(false, std::memory_order_relaxed);
80             }
81             bit++;
82         }
83         return result;
84     }
85 };
86 
87 static pending_signals_t s_pending_signals;
88 
89 /// List of event handlers.
90 static owning_lock<event_handler_list_t> s_event_handlers;
91 
92 /// Variables (one per signal) set when a signal is observed. This is inspected by a signal handler.
93 static volatile sig_atomic_t s_observed_signals[NSIG] = {};
94 
set_signal_observed(int sig,bool val)95 static void set_signal_observed(int sig, bool val) {
96     if (sig >= 0 &&
97         static_cast<size_t>(sig) < sizeof s_observed_signals / sizeof *s_observed_signals) {
98         s_observed_signals[sig] = val;
99     }
100 }
101 
102 /// Tests if one event instance matches the definition of an event class.
103 /// In case of a match, \p only_once indicates that the event cannot match again by nature.
handler_matches(const event_handler_t & classv,const event_t & instance,bool & only_once)104 static bool handler_matches(const event_handler_t &classv, const event_t &instance,
105                             bool &only_once) {
106     only_once = false;
107     if (classv.desc.type == event_type_t::any) return true;
108     if (classv.desc.type != instance.desc.type) return false;
109 
110     switch (classv.desc.type) {
111         case event_type_t::signal: {
112             return classv.desc.param1.signal == instance.desc.param1.signal;
113         }
114         case event_type_t::variable: {
115             return instance.desc.str_param1 == classv.desc.str_param1;
116         }
117         case event_type_t::process_exit: {
118             if (classv.desc.param1.pid == EVENT_ANY_PID) return true;
119             only_once = true;
120             return classv.desc.param1.pid == instance.desc.param1.pid;
121         }
122         case event_type_t::job_exit: {
123             const auto &jobspec = classv.desc.param1.jobspec;
124             if (jobspec.pid == EVENT_ANY_PID) return true;
125             only_once = true;
126             return jobspec.internal_job_id == instance.desc.param1.jobspec.internal_job_id;
127         }
128         case event_type_t::caller_exit: {
129             only_once = true;
130             return classv.desc.param1.caller_id == instance.desc.param1.caller_id;
131         }
132         case event_type_t::generic: {
133             return classv.desc.str_param1 == instance.desc.str_param1;
134         }
135         case event_type_t::any:
136         default: {
137             DIE("unexpected classv.type");
138             return false;
139         }
140     }
141 }
142 
143 /// Test if specified event is blocked.
event_is_blocked(parser_t & parser,const event_t & e)144 static int event_is_blocked(parser_t &parser, const event_t &e) {
145     (void)e;
146     const block_t *block;
147     size_t idx = 0;
148     while ((block = parser.block_at_index(idx++))) {
149         if (event_block_list_blocks_type(block->event_blocks)) return true;
150     }
151     return event_block_list_blocks_type(parser.global_event_blocks);
152 }
153 
event_get_desc(const parser_t & parser,const event_t & evt)154 wcstring event_get_desc(const parser_t &parser, const event_t &evt) {
155     const event_description_t &ed = evt.desc;
156     switch (ed.type) {
157         case event_type_t::signal: {
158             return format_string(_(L"signal handler for %ls (%ls)"), sig2wcs(ed.param1.signal),
159                                  signal_get_desc(ed.param1.signal));
160         }
161 
162         case event_type_t::variable: {
163             return format_string(_(L"handler for variable '%ls'"), ed.str_param1.c_str());
164         }
165 
166         case event_type_t::process_exit: {
167             return format_string(_(L"exit handler for process %d"), ed.param1.pid);
168         }
169 
170         case event_type_t::job_exit: {
171             const auto &jobspec = ed.param1.jobspec;
172             if (const job_t *j = parser.job_get_from_pid(jobspec.pid)) {
173                 return format_string(_(L"exit handler for job %d, '%ls'"), j->job_id(),
174                                      j->command_wcstr());
175             } else {
176                 return format_string(_(L"exit handler for job with pid %d"), jobspec.pid);
177             }
178         }
179 
180         case event_type_t::caller_exit: {
181             return _(L"exit handler for command substitution caller");
182         }
183 
184         case event_type_t::generic: {
185             return format_string(_(L"handler for generic event '%ls'"), ed.str_param1.c_str());
186         }
187         case event_type_t::any: {
188             DIE("Unreachable");
189         }
190         default:
191             DIE("Unknown event type");
192     }
193 }
194 
event_add_handler(std::shared_ptr<event_handler_t> eh)195 void event_add_handler(std::shared_ptr<event_handler_t> eh) {
196     if (eh->desc.type == event_type_t::signal) {
197         signal_handle(eh->desc.param1.signal);
198         set_signal_observed(eh->desc.param1.signal, true);
199     }
200 
201     s_event_handlers.acquire()->push_back(std::move(eh));
202 }
203 
event_remove_function_handlers(const wcstring & name)204 void event_remove_function_handlers(const wcstring &name) {
205     auto handlers = s_event_handlers.acquire();
206     auto begin = handlers->begin(), end = handlers->end();
207     handlers->erase(std::remove_if(begin, end,
208                                    [&](const shared_ptr<event_handler_t> &eh) {
209                                        return eh->function_name == name;
210                                    }),
211                     end);
212 }
213 
event_get_function_handlers(const wcstring & name)214 event_handler_list_t event_get_function_handlers(const wcstring &name) {
215     auto handlers = s_event_handlers.acquire();
216     event_handler_list_t result;
217     for (const shared_ptr<event_handler_t> &eh : *handlers) {
218         if (eh->function_name == name) {
219             result.push_back(eh);
220         }
221     }
222     return result;
223 }
224 
event_is_signal_observed(int sig)225 bool event_is_signal_observed(int sig) {
226     // We are in a signal handler! Don't allocate memory, etc.
227     bool result = false;
228     if (sig >= 0 && static_cast<unsigned long>(sig) <
229                         sizeof(s_observed_signals) / sizeof(*s_observed_signals)) {
230         result = s_observed_signals[sig];
231     }
232     return result;
233 }
234 
235 /// Perform the specified event. Since almost all event firings will not be matched by even a single
236 /// event handler, we make sure to optimize the 'no matches' path. This means that nothing is
237 /// allocated/initialized unless needed.
event_fire_internal(parser_t & parser,const event_t & event)238 static void event_fire_internal(parser_t &parser, const event_t &event) {
239     auto &ld = parser.libdata();
240     assert(ld.is_event >= 0 && "is_event should not be negative");
241     scoped_push<decltype(ld.is_event)> inc_event{&ld.is_event, ld.is_event + 1};
242 
243     // Suppress fish_trace during events.
244     scoped_push<bool> suppress_trace{&ld.suppress_fish_trace, true};
245 
246     // Capture the event handlers that match this event.
247     struct firing_handler_t {
248         std::shared_ptr<event_handler_t> handler;
249         bool delete_after_call;
250     };
251     std::vector<firing_handler_t> fire;
252     {
253         for (const auto &handler : *s_event_handlers.acquire()) {
254             // Check if this event is a match.
255             bool only_once = false;
256             if (!handler_matches(*handler, event, only_once)) {
257                 continue;
258             }
259 
260             // If the nature of the event means it can't be fired more than once, deregister the
261             // event. This also works around a bug where jobs run without job control (no separate
262             // pgrp) cause handlers to run for each subsequent job started without job control
263             // (#7721). We can't erase it here because we check if the event is still extant before
264             // actually calling it below, so we instead push it along with its "delete after
265             // calling" value.
266             fire.push_back(firing_handler_t{handler, only_once});
267         }
268     }
269 
270     // Iterate over our list of matching events. Fire the ones that are still present.
271     for (const auto &firing_event : fire) {
272         auto &handler = firing_event.handler;
273         // Only fire if this event is still present.
274         // TODO: this is kind of crazy. We want to support removing (and thereby suppressing) an
275         // event handler from another, but we also don't want to hold the lock across callouts. How
276         // can we make this less silly?
277         {
278             auto event_handlers = s_event_handlers.acquire();
279             if (!contains(*event_handlers, handler)) {
280                 continue;
281             }
282 
283             // Delete the event before firing it so we don't have to lock and unlock the event
284             // handlers list when handing control off to the handler.
285             if (firing_event.delete_after_call) {
286                 FLOGF(event, L"Pruning handler '%ls' before firing", event.desc.str_param1.c_str());
287                 for (auto event_handler = event_handlers->begin();
288                      event_handler != event_handlers->end(); ++event_handler) {
289                     if (event_handler->get() == firing_event.handler.get()) {
290                         event_handlers->erase(event_handler);
291                         break;
292                     }
293                 }
294             }
295         }
296 
297         // Construct a buffer to evaluate, starting with the function name and then all the
298         // arguments.
299         wcstring buffer = handler->function_name;
300         for (const wcstring &arg : event.arguments) {
301             buffer.push_back(L' ');
302             buffer.append(escape_string(arg, ESCAPE_ALL));
303         }
304 
305         // Event handlers are not part of the main flow of code, so they are marked as
306         // non-interactive.
307         scoped_push<bool> interactive{&ld.is_interactive, false};
308         auto prev_statuses = parser.get_last_statuses();
309 
310         FLOGF(event, L"Firing event '%ls'", event.desc.str_param1.c_str());
311         block_t *b = parser.push_block(block_t::event_block(event));
312         parser.eval(buffer, io_chain_t());
313         parser.pop_block(b);
314         parser.set_last_statuses(std::move(prev_statuses));
315     }
316 }
317 
318 /// Handle all pending signal events.
event_fire_delayed(parser_t & parser)319 void event_fire_delayed(parser_t &parser) {
320     auto &ld = parser.libdata();
321     // Do not invoke new event handlers from within event handlers.
322     if (ld.is_event) return;
323     // Do not invoke new event handlers if we are unwinding (#6649).
324     if (signal_check_cancel()) return;
325 
326     std::vector<shared_ptr<const event_t>> to_send;
327     to_send.swap(ld.blocked_events);
328     assert(ld.blocked_events.empty());
329 
330     // Append all signal events to to_send.
331     auto signals = s_pending_signals.acquire_pending();
332     if (signals.any()) {
333         for (uint32_t sig = 0; sig < signals.size(); sig++) {
334             if (signals.test(sig)) {
335                 // HACK: The only variables we change in response to a *signal*
336                 // are $COLUMNS and $LINES.
337                 // Do that now.
338                 if (sig == SIGWINCH) {
339                     (void)termsize_container_t::shared().updating(parser);
340                 }
341                 auto e = std::make_shared<event_t>(event_type_t::signal);
342                 e->desc.param1.signal = sig;
343                 e->arguments.push_back(sig2wcs(sig));
344                 to_send.push_back(std::move(e));
345             }
346         }
347     }
348 
349     // Fire or re-block all events.
350     for (const auto &evt : to_send) {
351         if (event_is_blocked(parser, *evt)) {
352             ld.blocked_events.push_back(evt);
353         } else {
354             event_fire_internal(parser, *evt);
355         }
356     }
357 }
358 
event_enqueue_signal(int signal)359 void event_enqueue_signal(int signal) {
360     // Beware, we are in a signal handler
361     s_pending_signals.mark(signal);
362 }
363 
event_fire(parser_t & parser,const event_t & event)364 void event_fire(parser_t &parser, const event_t &event) {
365     // Fire events triggered by signals.
366     event_fire_delayed(parser);
367 
368     if (event_is_blocked(parser, event)) {
369         parser.libdata().blocked_events.push_back(std::make_shared<event_t>(event));
370     } else {
371         event_fire_internal(parser, event);
372     }
373 }
374 
event_name_for_type(event_type_t type)375 static const wchar_t *event_name_for_type(event_type_t type) {
376     switch (type) {
377         case event_type_t::any:
378             return L"any";
379         case event_type_t::signal:
380             return L"signal";
381         case event_type_t::variable:
382             return L"variable";
383         case event_type_t::process_exit:
384             return L"process-exit";
385         case event_type_t::job_exit:
386             return L"job-exit";
387         case event_type_t::caller_exit:
388             return L"caller-exit";
389         case event_type_t::generic:
390             return L"generic";
391     }
392     return L"";
393 }
394 
395 const wchar_t *const event_filter_names[] = {L"signal",       L"variable", L"exit",
396                                              L"process-exit", L"job-exit", L"caller-exit",
397                                              L"generic",      nullptr};
398 
filter_matches_event(const wcstring & filter,event_type_t type)399 static bool filter_matches_event(const wcstring &filter, event_type_t type) {
400     if (filter.empty()) return true;
401     switch (type) {
402         case event_type_t::any:
403             return false;
404         case event_type_t::signal:
405             return filter == L"signal";
406         case event_type_t::variable:
407             return filter == L"variable";
408         case event_type_t::process_exit:
409             return filter == L"process-exit" || filter == L"exit";
410         case event_type_t::job_exit:
411             return filter == L"job-exit" || filter == L"exit";
412         case event_type_t::caller_exit:
413             return filter == L"process-exit" || filter == L"exit";
414         case event_type_t::generic:
415             return filter == L"generic";
416     }
417     DIE("Unreachable");
418 }
419 
event_print(io_streams_t & streams,const wcstring & type_filter)420 void event_print(io_streams_t &streams, const wcstring &type_filter) {
421     event_handler_list_t tmp = *s_event_handlers.acquire();
422     std::sort(tmp.begin(), tmp.end(),
423               [](const shared_ptr<event_handler_t> &e1, const shared_ptr<event_handler_t> &e2) {
424                   const event_description_t &d1 = e1->desc;
425                   const event_description_t &d2 = e2->desc;
426                   if (d1.type != d2.type) {
427                       return d1.type < d2.type;
428                   }
429                   switch (d1.type) {
430                       case event_type_t::signal:
431                           return d1.param1.signal < d2.param1.signal;
432                       case event_type_t::process_exit:
433                           return d1.param1.pid < d2.param1.pid;
434                       case event_type_t::job_exit:
435                           return d1.param1.jobspec.pid < d2.param1.jobspec.pid;
436                       case event_type_t::caller_exit:
437                           return d1.param1.caller_id < d2.param1.caller_id;
438                       case event_type_t::variable:
439                       case event_type_t::any:
440                       case event_type_t::generic:
441                           return d1.str_param1 < d2.str_param1;
442                   }
443                   DIE("Unreachable");
444               });
445 
446     maybe_t<event_type_t> last_type{};
447     for (const shared_ptr<event_handler_t> &evt : tmp) {
448         // If we have a filter, skip events that don't match.
449         if (!filter_matches_event(type_filter, evt->desc.type)) {
450             continue;
451         }
452 
453         if (!last_type || *last_type != evt->desc.type) {
454             if (last_type) streams.out.append(L"\n");
455             last_type = evt->desc.type;
456             streams.out.append_format(L"Event %ls\n", event_name_for_type(*last_type));
457         }
458         switch (evt->desc.type) {
459             case event_type_t::signal:
460                 streams.out.append_format(L"%ls %ls\n", sig2wcs(evt->desc.param1.signal),
461                                           evt->function_name.c_str());
462                 break;
463             case event_type_t::process_exit:
464             case event_type_t::job_exit:
465                 break;
466             case event_type_t::caller_exit:
467                 streams.out.append_format(L"caller-exit %ls\n", evt->function_name.c_str());
468                 break;
469             case event_type_t::variable:
470             case event_type_t::generic:
471                 streams.out.append_format(L"%ls %ls\n", evt->desc.str_param1.c_str(),
472                                           evt->function_name.c_str());
473                 break;
474             case event_type_t::any:
475                 DIE("Unreachable");
476             default:
477                 streams.out.append_format(L"%ls\n", evt->function_name.c_str());
478                 break;
479         }
480     }
481 }
482 
event_fire_generic(parser_t & parser,const wchar_t * name,const wcstring_list_t * args)483 void event_fire_generic(parser_t &parser, const wchar_t *name, const wcstring_list_t *args) {
484     assert(name && "Null name");
485 
486     event_t ev(event_type_t::generic);
487     ev.desc.str_param1 = name;
488     if (args) ev.arguments = *args;
489     event_fire(parser, ev);
490 }
491 
signal(int sig)492 event_description_t event_description_t::signal(int sig) {
493     event_description_t event(event_type_t::signal);
494     event.param1.signal = sig;
495     return event;
496 }
497 
variable(wcstring str)498 event_description_t event_description_t::variable(wcstring str) {
499     event_description_t event(event_type_t::variable);
500     event.str_param1 = std::move(str);
501     return event;
502 }
503 
generic(wcstring str)504 event_description_t event_description_t::generic(wcstring str) {
505     event_description_t event(event_type_t::generic);
506     event.str_param1 = std::move(str);
507     return event;
508 }
509 
510 // static
variable(wcstring name,wcstring_list_t args)511 event_t event_t::variable(wcstring name, wcstring_list_t args) {
512     event_t evt{event_type_t::variable};
513     evt.desc.str_param1 = std::move(name);
514     evt.arguments = std::move(args);
515     return evt;
516 }
517 
518 // static
process_exit(pid_t pid,int status)519 event_t event_t::process_exit(pid_t pid, int status) {
520     event_t evt{event_type_t::process_exit};
521     evt.desc.param1.pid = pid;
522     evt.arguments.reserve(3);
523     evt.arguments.push_back(L"PROCESS_EXIT");
524     evt.arguments.push_back(to_string(pid));
525     evt.arguments.push_back(to_string(status));
526     return evt;
527 }
528 
529 // static
job_exit(pid_t pid,internal_job_id_t jid)530 event_t event_t::job_exit(pid_t pid, internal_job_id_t jid) {
531     event_t evt{event_type_t::job_exit};
532     evt.desc.param1.jobspec = {pid, jid};
533     evt.arguments.reserve(3);
534     evt.arguments.push_back(L"JOB_EXIT");
535     evt.arguments.push_back(to_string(pid));
536     evt.arguments.push_back(L"0");  // historical
537     return evt;
538 }
539 
540 // static
caller_exit(uint64_t caller_id,int job_id)541 event_t event_t::caller_exit(uint64_t caller_id, int job_id) {
542     event_t evt{event_type_t::caller_exit};
543     evt.desc.param1.caller_id = caller_id;
544     evt.arguments.reserve(3);
545     evt.arguments.push_back(L"JOB_EXIT");
546     evt.arguments.push_back(to_string(job_id));
547     evt.arguments.push_back(L"0");  // historical
548     return evt;
549 }
550