1 // Functions for handling event triggers 2 // 3 // Because most of these functions can be called by signal handler, it is important to make it well 4 // defined when these functions produce output or perform memory allocations, since such functions 5 // may not be safely called by signal handlers. 6 #ifndef FISH_EVENT_H 7 #define FISH_EVENT_H 8 9 #include <unistd.h> 10 11 #include <map> 12 #include <memory> 13 #include <vector> 14 15 #include "common.h" 16 #include "io.h" 17 18 /// The process id that is used to match any process id. 19 #define EVENT_ANY_PID 0 20 21 /// Enumeration of event types. 22 enum class event_type_t { 23 /// Matches any event type (Not always any event, as the function name may limit the choice as 24 /// well. 25 any, 26 /// An event triggered by a signal. 27 signal, 28 /// An event triggered by a variable update. 29 variable, 30 /// An event triggered by a process exit. 31 process_exit, 32 /// An event triggered by a job exit. 33 job_exit, 34 /// An event triggered by a job exit, triggering the 'caller'-style events only. 35 caller_exit, 36 /// A generic event. 37 generic, 38 }; 39 40 /// Null-terminated list of valid event filter names. 41 /// These are what are valid to pass to 'functions --handlers-type' 42 extern const wchar_t *const event_filter_names[]; 43 44 /// Properties of an event. 45 struct event_description_t { 46 /// Helper type for on-job-exit events. 47 struct job_spec_t { 48 // pid requested by the event, or ANY_PID for all. 49 pid_t pid; 50 51 // internal_job_id of the job to match. 52 // If this is 0, we match either all jobs (pid == ANY_PID) or no jobs (otherwise). 53 uint64_t internal_job_id; 54 }; 55 56 /// The event type. 57 event_type_t type; 58 59 /// The type-specific parameter. The int types are one of the following: 60 /// 61 /// signal: Signal number for signal-type events.Use EVENT_ANY_SIGNAL to match any signal 62 /// pid: Process id for process-type events. Use EVENT_ANY_PID to match any pid. 63 /// jobspec: Info for on-job-exit events. 64 /// caller_id: Internal job id for caller_exit type events 65 union { 66 int signal; 67 pid_t pid; 68 job_spec_t jobspec; 69 uint64_t caller_id; 70 } param1{}; 71 72 /// The string types are one of the following: 73 /// 74 /// variable: Variable name for variable-type events. 75 /// param: The parameter describing this generic event. 76 wcstring str_param1{}; 77 event_description_tevent_description_t78 explicit event_description_t(event_type_t t) : type(t) {} 79 static event_description_t signal(int sig); 80 static event_description_t variable(wcstring str); 81 static event_description_t generic(wcstring str); 82 }; 83 84 /// Represents a handler for an event. 85 struct event_handler_t { 86 /// Properties of the event to match. 87 event_description_t desc; 88 89 /// Name of the function to invoke. 90 wcstring function_name{}; 91 event_handler_tevent_handler_t92 explicit event_handler_t(event_type_t t) : desc(t) {} event_handler_tevent_handler_t93 event_handler_t(event_description_t d, wcstring name) 94 : desc(std::move(d)), function_name(std::move(name)) {} 95 }; 96 using event_handler_list_t = std::vector<std::shared_ptr<event_handler_t>>; 97 98 /// Represents a event that is fired, or capable of being fired. 99 struct event_t { 100 /// Properties of the event. 101 event_description_t desc; 102 103 /// Arguments to any handler. 104 wcstring_list_t arguments{}; 105 event_tevent_t106 explicit event_t(event_type_t t) : desc(t) {} 107 108 /// Create an event_type_t::variable event. 109 static event_t variable(wcstring name, wcstring_list_t args); 110 111 /// Create a PROCESS_EXIT event. 112 static event_t process_exit(pid_t pid, int status); 113 114 /// Create a JOB_EXIT event. The pgid should be positive. 115 /// The reported status is always 0 for historical reasons. 116 static event_t job_exit(pid_t pgid, internal_job_id_t jid); 117 118 /// Create a caller_exit event. 119 static event_t caller_exit(uint64_t internal_job_id, int job_id); 120 }; 121 122 class parser_t; 123 124 /// Add an event handler. 125 void event_add_handler(std::shared_ptr<event_handler_t> eh); 126 127 /// Remove all events for the given function name. 128 void event_remove_function_handlers(const wcstring &name); 129 130 /// Return all event handlers for the given function. 131 event_handler_list_t event_get_function_handlers(const wcstring &name); 132 133 /// Returns whether an event listener is registered for the given signal. This is safe to call from 134 /// a signal handler. 135 bool event_is_signal_observed(int signal); 136 137 /// Fire the specified event \p event, executing it on \p parser. 138 void event_fire(parser_t &parser, const event_t &event); 139 140 /// Fire all delayed events attached to the given parser. 141 void event_fire_delayed(parser_t &parser); 142 143 /// Enqueue a signal event. Invoked from a signal handler. 144 void event_enqueue_signal(int signal); 145 146 /// Print all events. If type_filter is not empty, only output events with that type. 147 void event_print(io_streams_t &streams, const wcstring &type_filter); 148 149 /// Returns a string describing the specified event. 150 wcstring event_get_desc(const parser_t &parser, const event_t &e); 151 152 /// Fire a generic event with the specified name. 153 void event_fire_generic(parser_t &parser, const wchar_t *name, 154 const wcstring_list_t *args = nullptr); 155 156 #endif 157