1 // Prototypes for utilities for keeping track of jobs, processes and subshells, as well as signal
2 // handling functions for tracking children. These functions do not themselves launch new processes,
3 // the exec library will call proc to create representations of the running jobs as needed.
4 #ifndef FISH_PROC_H
5 #define FISH_PROC_H
6 #include "config.h"  // IWYU pragma: keep
7 
8 #include <signal.h>
9 #include <stddef.h>
10 #include <sys/time.h>  // IWYU pragma: keep
11 #include <sys/wait.h>  // IWYU pragma: keep
12 #include <unistd.h>
13 
14 #include <deque>
15 #include <memory>
16 #include <vector>
17 
18 #include "common.h"
19 #include "event.h"
20 #include "global_safety.h"
21 #include "io.h"
22 #include "parse_tree.h"
23 #include "topic_monitor.h"
24 #include "wait_handle.h"
25 
26 /// Types of processes.
27 enum class process_type_t {
28     /// A regular external command.
29     external,
30     /// A builtin command.
31     builtin,
32     /// A shellscript function.
33     function,
34     /// A block of commands, represented as a node.
35     block_node,
36     /// The exec builtin.
37     exec,
38 };
39 
40 enum class job_control_t {
41     all,
42     interactive,
43     none,
44 };
45 
46 namespace ast {
47 struct statement_t;
48 }
49 
50 class job_group_t;
51 using job_group_ref_t = std::shared_ptr<job_group_t>;
52 
53 /// A proc_status_t is a value type that encapsulates logic around exited vs stopped vs signaled,
54 /// etc.
55 class proc_status_t {
56     int status_{};
57 
58     /// If set, there is no actual status to report, e.g. background or variable assignment.
59     bool empty_{};
60 
proc_status_t(int status)61     explicit proc_status_t(int status) : status_(status), empty_(false) {}
62 
proc_status_t(int status,bool empty)63     proc_status_t(int status, bool empty) : status_(status), empty_(empty) {}
64 
65     /// Encode a return value \p ret and signal \p sig into a status value like waitpid() does.
w_exitcode(int ret,int sig)66     static constexpr int w_exitcode(int ret, int sig) {
67 #ifdef W_EXITCODE
68         return W_EXITCODE(ret, sig);
69 #else
70         return ((ret) << 8 | (sig));
71 #endif
72     }
73 
74    public:
75     proc_status_t() = default;
76 
77     /// Construct from a status returned from a waitpid call.
from_waitpid(int status)78     static proc_status_t from_waitpid(int status) { return proc_status_t(status); }
79 
80     /// Construct directly from an exit code.
from_exit_code(int ret)81     static proc_status_t from_exit_code(int ret) {
82         // Some paranoia.
83         constexpr int zerocode = w_exitcode(0, 0);
84         static_assert(WIFEXITED(zerocode), "Synthetic exit status not reported as exited");
85 
86         assert(ret < 256);
87         return proc_status_t(w_exitcode(ret, 0 /* sig */));
88     }
89 
90     /// Construct directly from a signal.
from_signal(int sig)91     static proc_status_t from_signal(int sig) {
92         return proc_status_t(w_exitcode(0 /* ret */, sig));
93     }
94 
95     /// Construct an empty status_t (e.g. `set foo bar`).
empty()96     static proc_status_t empty() {
97         bool empty = true;
98         return proc_status_t(0, empty);
99     }
100 
101     /// \return if we are stopped (as in SIGSTOP).
stopped()102     bool stopped() const { return WIFSTOPPED(status_); }
103 
104     /// \return if we are continued (as in SIGCONT).
continued()105     bool continued() const { return WIFCONTINUED(status_); }
106 
107     /// \return if we exited normally (not a signal).
normal_exited()108     bool normal_exited() const { return WIFEXITED(status_); }
109 
110     /// \return if we exited because of a signal.
signal_exited()111     bool signal_exited() const { return WIFSIGNALED(status_); }
112 
113     /// \return the signal code, given that we signal exited.
signal_code()114     int signal_code() const {
115         assert(signal_exited() && "Process is not signal exited");
116         return WTERMSIG(status_);
117     }
118 
119     /// \return the exit code, given that we normal exited.
exit_code()120     int exit_code() const {
121         assert(normal_exited() && "Process is not normal exited");
122         return WEXITSTATUS(status_);
123     }
124 
125     /// \return if this status represents success.
is_success()126     bool is_success() const { return normal_exited() && exit_code() == EXIT_SUCCESS; }
127 
128     /// \return if this status is empty.
is_empty()129     bool is_empty() const { return empty_; }
130 
131     /// \return the value appropriate to populate $status.
status_value()132     int status_value() const {
133         if (signal_exited()) {
134             return 128 + signal_code();
135         } else if (normal_exited()) {
136             return exit_code();
137         } else {
138             DIE("Process is not exited");
139         }
140     }
141 };
142 
143 /// A structure representing a "process" internal to fish. This is backed by a pthread instead of a
144 /// separate process.
145 class internal_proc_t {
146     /// An identifier for internal processes.
147     /// This is used for logging purposes only.
148     const uint64_t internal_proc_id_;
149 
150     /// Whether the process has exited.
151     std::atomic<bool> exited_{};
152 
153     /// If the process has exited, its status code.
154     std::atomic<proc_status_t> status_{};
155 
156    public:
157     /// \return if this process has exited.
exited()158     bool exited() const { return exited_.load(std::memory_order_acquire); }
159 
160     /// Mark this process as exited, with the given status.
161     void mark_exited(proc_status_t status);
162 
get_status()163     proc_status_t get_status() const {
164         assert(exited() && "Process is not exited");
165         return status_.load(std::memory_order_relaxed);
166     }
167 
get_id()168     uint64_t get_id() const { return internal_proc_id_; }
169 
170     internal_proc_t();
171 };
172 
173 /// 0 should not be used; although it is not a valid PGID in userspace,
174 ///   the Linux kernel will use it for kernel processes.
175 /// -1 should not be used; it is a possible return value of the getpgid()
176 ///   function
177 enum { INVALID_PID = -2 };
178 
179 /// A structure representing a single fish process. Contains variables for tracking process state
180 /// and the process argument list. Actually, a fish process can be either a regular external
181 /// process, an internal builtin which may or may not spawn a fake IO process during execution, a
182 /// shellscript function or a block of commands to be evaluated by calling eval. Lastly, this
183 /// process can be the result of an exec command. The role of this process_t is determined by the
184 /// type field, which can be one of process_type_t::external, process_type_t::builtin,
185 /// process_type_t::function, process_type_t::exec.
186 ///
187 /// The process_t contains information on how the process should be started, such as command name
188 /// and arguments, as well as runtime information on the status of the actual physical process which
189 /// represents it. Shellscript functions, builtins and blocks of code may all need to spawn an
190 /// external process that handles the piping and redirecting of IO for them.
191 ///
192 /// If the process is of type process_type_t::external or process_type_t::exec, argv is the argument
193 /// array and actual_cmd is the absolute path of the command to execute.
194 ///
195 /// If the process is of type process_type_t::builtin, argv is the argument vector, and argv[0] is
196 /// the name of the builtin command.
197 ///
198 /// If the process is of type process_type_t::function, argv is the argument vector, and argv[0] is
199 /// the name of the shellscript function.
200 class parser_t;
201 class process_t {
202    public:
203     process_t();
204 
205     /// Note whether we are the first and/or last in the job
206     bool is_first_in_job{false};
207     bool is_last_in_job{false};
208 
209     /// Type of process.
210     process_type_t type{process_type_t::external};
211 
212     /// For internal block processes only, the node of the statement.
213     /// This is always either block, ifs, or switchs, never boolean or decorated.
214     parsed_source_ref_t block_node_source{};
215     const ast::statement_t *internal_block_node{};
216 
217     struct concrete_assignment {
218         wcstring variable_name;
219         wcstring_list_t values;
220     };
221     /// The expanded variable assignments for this process, as specified by the `a=b cmd` syntax.
222     std::vector<concrete_assignment> variable_assignments;
223 
224     /// Sets argv.
set_argv(wcstring_list_t argv)225     void set_argv(wcstring_list_t argv) { argv_ = std::move(argv); }
226 
227     /// Returns argv.
argv()228     const wcstring_list_t &argv() { return argv_; }
229 
230     /// Returns argv[0], or nullptr.
argv0()231     const wchar_t *argv0() const { return argv_.empty() ? nullptr : argv_.front().c_str(); }
232 
233     /// Redirection list getter and setter.
redirection_specs()234     const redirection_spec_list_t &redirection_specs() const { return proc_redirection_specs_; }
235 
set_redirection_specs(redirection_spec_list_t specs)236     void set_redirection_specs(redirection_spec_list_t specs) {
237         this->proc_redirection_specs_ = std::move(specs);
238     }
239 
240     /// Store the current topic generations. That is, right before the process is launched, record
241     /// the generations of all topics; then we can tell which generation values have changed after
242     /// launch. This helps us avoid spurious waitpid calls.
243     void check_generations_before_launch();
244 
245     /// Mark that this process was part of a pipeline which was aborted.
246     /// The process was never successfully launched; give it a status of EXIT_FAILURE.
247     void mark_aborted_before_launch();
248 
249     /// \return whether this process type is internal (block, function, or builtin).
250     bool is_internal() const;
251 
252     /// \return the wait handle for the process, creating it if \p create is set.
253     /// This will return nullptr if the process does not have a pid (i.e. is not external).
254     wait_handle_ref_t get_wait_handle(bool create = true);
255 
256     /// Actual command to pass to exec in case of process_type_t::external or process_type_t::exec.
257     wcstring actual_cmd;
258 
259     /// Generation counts for reaping.
260     generation_list_t gens_{};
261 
262     /// Process ID
263     pid_t pid{0};
264 
265     /// If we are an "internal process," that process.
266     std::shared_ptr<internal_proc_t> internal_proc_{};
267 
268     /// File descriptor that pipe output should bind to.
269     int pipe_write_fd{0};
270 
271     /// True if process has completed.
272     bool completed{false};
273 
274     /// True if process has stopped.
275     bool stopped{false};
276 
277     /// Reported status value.
278     proc_status_t status{};
279 
280     /// Last time of cpu time check.
281     struct timeval last_time {};
282 
283     /// Number of jiffies spent in process at last cpu time check.
284     unsigned long last_jiffies{0};
285 
286     // No copying.
287     process_t(const process_t &rhs) = delete;
288     void operator=(const process_t &rhs) = delete;
289 
290    private:
291     wcstring_list_t argv_;
292     redirection_spec_list_t proc_redirection_specs_;
293 
294     // The wait handle. This is constructed lazily, and cached.
295     wait_handle_ref_t wait_handle_{};
296 };
297 
298 using process_ptr_t = std::unique_ptr<process_t>;
299 using process_list_t = std::vector<process_ptr_t>;
300 
301 /// A struct representing a job. A job is a pipeline of one or more processes.
302 class job_t {
303    public:
304     /// A set of jobs properties. These are immutable: they do not change for the lifetime of the
305     /// job.
306     struct properties_t {
307         /// Whether the specified job is a part of a subshell, event handler or some other form of
308         /// special job that should not be reported.
309         bool skip_notification{};
310 
311         /// Whether the job had the background ampersand when constructed, e.g. /bin/echo foo &
312         /// Note that a job may move between foreground and background; this just describes what the
313         /// initial state should be.
314         bool initial_background{};
315 
316         /// Whether the job has the 'time' prefix and so we should print timing for this job.
317         bool wants_timing{};
318 
319         /// Whether this job was created as part of an event handler.
320         bool from_event_handler{};
321 
322         /// Whether the job is under job control, i.e. has its own pgrp.
323         bool job_control{};
324     };
325 
326    private:
327     /// Set of immutable job properties.
328     const properties_t properties;
329 
330     /// The original command which led to the creation of this job. It is used for displaying
331     /// messages about job status on the terminal.
332     const wcstring command_str;
333 
334     // No copying.
335     job_t(const job_t &rhs) = delete;
336     void operator=(const job_t &) = delete;
337 
338    public:
339     job_t(const properties_t &props, wcstring command_str);
340     ~job_t();
341 
342     /// Returns the command as a wchar_t *. */
command_wcstr()343     const wchar_t *command_wcstr() const { return command_str.c_str(); }
344 
345     /// Returns the command.
command()346     const wcstring &command() const { return command_str; }
347 
348     /// \return whether it is OK to reap a given process. Sometimes we want to defer reaping a
349     /// process if it is the group leader and the job is not yet constructed, because then we might
350     /// also reap the process group and then we cannot add new processes to the group.
can_reap(const process_ptr_t & p)351     bool can_reap(const process_ptr_t &p) const {
352         if (p->completed) {
353             // Can't reap twice.
354             return false;
355         } else if (p->pid && !is_constructed() && this->get_pgid() == maybe_t<pid_t>{p->pid}) {
356             // p is the the group leader in an under-construction job.
357             return false;
358         } else {
359             return true;
360         }
361     }
362 
363     /// Returns a truncated version of the job string. Used when a message has already been emitted
364     /// containing the full job string and job id, but using the job id alone would be confusing
365     /// due to reuse of freed job ids. Prevents overloading the debug comments with the full,
366     /// untruncated job string when we don't care what the job is, only which of the currently
367     /// running jobs it is.
preview()368     wcstring preview() const {
369         if (processes.empty()) return L"";
370         // Note argv0 may be empty in e.g. a block process.
371         const wchar_t *argv0 = processes.front()->argv0();
372         wcstring result = argv0 ? argv0 : L"null";
373         return result + L" ...";
374     }
375 
376     /// All the processes in this job.
377     process_list_t processes;
378 
379     // The group containing this job.
380     // This is never null and not changed after construction.
381     job_group_ref_t group{};
382 
383     /// \return the pgid for the job, based on the job group.
384     /// This may be none if the job consists of just internal fish functions or builtins.
385     /// This may also be fish itself.
386     maybe_t<pid_t> get_pgid() const;
387 
388     /// \return the pid of the last external process in the job.
389     /// This may be none if the job consists of just internal fish functions or builtins.
390     /// This will never be fish's own pid.
391     maybe_t<pid_t> get_last_pid() const;
392 
393     /// The id of this job.
394     /// This is user-visible, is recycled, and may be -1.
395     job_id_t job_id() const;
396 
397     /// A non-user-visible, never-recycled job ID.
398     const internal_job_id_t internal_job_id;
399 
400     /// Flags associated with the job.
401     struct flags_t {
402         /// Whether the specified job is completely constructed: every process in the job has been
403         /// forked, etc.
404         bool constructed{false};
405 
406         /// Whether the user has been told about stopped job.
407         bool notified{false};
408 
409         /// Whether the exit status should be negated. This flag can only be set by the not builtin.
410         bool negate{false};
411 
412         /// This job is disowned, and should be removed from the active jobs list.
413         bool disown_requested{false};
414 
415         // Indicates that we are the "group root." Any other jobs using this tree are nested.
416         bool is_group_root{false};
417 
418     } job_flags{};
419 
420     /// Access the job flags.
flags()421     const flags_t &flags() const { return job_flags; }
422 
423     /// Access mutable job flags.
mut_flags()424     flags_t &mut_flags() { return job_flags; }
425 
426     // \return whether we should print timing information.
wants_timing()427     bool wants_timing() const { return properties.wants_timing; }
428 
429     /// \return if we want job control.
wants_job_control()430     bool wants_job_control() const { return properties.job_control; }
431 
432     /// \return whether this job is initially going to run in the background, because & was
433     /// specified.
is_initially_background()434     bool is_initially_background() const { return properties.initial_background; }
435 
436     /// Mark this job as constructed. The job must not have previously been marked as constructed.
437     void mark_constructed();
438 
439     /// \return whether we have internal or external procs, respectively.
440     /// Internal procs are builtins, blocks, and functions.
441     /// External procs include exec and external.
442     bool has_internal_proc() const;
443     bool has_external_proc() const;
444 
445     // Helper functions to check presence of flags on instances of jobs
446     /// The job has been fully constructed, i.e. all its member processes have been launched
is_constructed()447     bool is_constructed() const { return flags().constructed; }
448     /// The job is complete, i.e. all its member processes have been reaped
449     bool is_completed() const;
450     /// The job is in a stopped state
451     bool is_stopped() const;
452     /// The job is OK to be externally visible, e.g. to the user via `jobs`
is_visible()453     bool is_visible() const {
454         return !is_completed() && is_constructed() && !flags().disown_requested;
455     }
skip_notification()456     bool skip_notification() const { return properties.skip_notification; }
from_event_handler()457     bool from_event_handler() const { return properties.from_event_handler; }
458 
459     /// \return whether this job's group is in the foreground.
460     bool is_foreground() const;
461 
462     /// \return whether we should report process exit events.
463     /// This implements some historical behavior which has not been justified.
464     bool should_report_process_exits() const;
465 
466     /// \return whether this job and its parent chain are fully constructed.
467     bool job_chain_is_fully_constructed() const;
468 
469     /// Continues running a job, which may be stopped, or may just have started.
470     /// This will send SIGCONT if the job is stopped.
471     /// If \p in_foreground is set, then wait for the job to stop or complete;
472     /// otherwise do not wait for the job.
473     void continue_job(parser_t &parser, bool in_foreground = true);
474 
475     /// Send the specified signal to all processes in this job.
476     /// \return true on success, false on failure.
477     bool signal(int signal);
478 
479     /// \returns the statuses for this job.
480     maybe_t<statuses_t> get_statuses() const;
481 };
482 
483 /// Whether this shell is attached to a tty.
484 bool is_interactive_session();
485 void set_interactive_session(bool flag);
486 
487 /// Whether we are a login shell.
488 bool get_login();
489 void mark_login();
490 
491 /// If this flag is set, fish will never fork or run execve. It is used to put fish into a syntax
492 /// verifier mode where fish tries to validate the syntax of a file but doesn't actually do
493 /// anything.
494 bool no_exec();
495 void mark_no_exec();
496 
497 // List of jobs.
498 typedef std::deque<shared_ptr<job_t>> job_list_t;
499 
500 /// The current job control mode.
501 ///
502 /// Must be one of job_control_t::all, job_control_t::interactive and job_control_t::none.
503 job_control_t get_job_control_mode();
504 void set_job_control_mode(job_control_t mode);
505 
506 /// Notify the user about stopped or terminated jobs, and delete completed jobs from the job list.
507 /// If \p interactive is set, allow removing interactive jobs; otherwise skip them.
508 /// \return whether text was printed to stdout.
509 class parser_t;
510 bool job_reap(parser_t &parser, bool interactive);
511 
512 /// \return the list of background jobs which we should warn the user about, if the user attempts to
513 /// exit. An empty result (common) means no such jobs.
514 job_list_t jobs_requiring_warning_on_exit(const parser_t &parser);
515 
516 /// Print the exit warning for the given jobs, which should have been obtained via
517 /// jobs_requiring_warning_on_exit().
518 void print_exit_warning_for_jobs(const job_list_t &jobs);
519 
520 /// Use the procfs filesystem to look up how many jiffies of cpu time was used by this process. This
521 /// function is only available on systems with the procfs file entry 'stat', i.e. Linux.
522 unsigned long proc_get_jiffies(process_t *p);
523 
524 /// Update process time usage for all processes by calling the proc_get_jiffies function for every
525 /// process of every job.
526 void proc_update_jiffies(parser_t &parser);
527 
528 /// Perform a set of simple sanity checks on the job list. This includes making sure that only one
529 /// job is in the foreground, that every process is in a valid state, etc.
530 void proc_sanity_check(const parser_t &parser);
531 
532 /// Initializations.
533 void proc_init();
534 
535 /// Wait for any process finishing, or receipt of a signal.
536 void proc_wait_any(parser_t &parser);
537 
538 /// Set and get whether we are in initialization.
539 // Hackish. In order to correctly report the origin of code with no associated file, we need to
540 // know whether it's run during initialization or not.
541 void set_is_within_fish_initialization(bool flag);
542 bool is_within_fish_initialization();
543 
544 /// Send SIGHUP to the list \p jobs, excepting those which are in fish's pgroup.
545 void hup_jobs(const job_list_t &jobs);
546 
547 /// Give ownership of the terminal to the specified job group, if it wants it.
548 ///
549 /// \param jg The job group to give the terminal to.
550 /// \param continuing_from_stopped If this variable is set, we are giving back control to a job that
551 /// was previously stopped. In that case, we need to set the terminal attributes to those saved in
552 /// the job.
553 /// \return 1 if transferred, 0 if no transfer was necessary, -1 on error.
554 int terminal_maybe_give_to_job_group(const job_group_t *jg, bool continuing_from_stopped);
555 
556 /// Add a job to the list of PIDs/PGIDs we wait on even though they are not associated with any
557 /// jobs. Used to avoid zombie processes after disown.
558 void add_disowned_job(const job_t *j);
559 
560 bool have_proc_stat();
561 
562 #endif
563