• R/O
  • SSH
  • HTTPS

yash: Commit


Commit MetaInfo

Revision3969 (tree)
Time2019-01-14 16:36:37
Authormagicant

Log Message

Neglect jobs in subshell with no-fork optimization (#38823)

When the no-fork optimization takes effect on a subshell, it was not
forgetting the original shell's jobs. The subshell was able to falsely
await the original shell's jobs.

The subshell should behave as if it is a child process created by the
fork_and_reset function. This commit extracts part of it as the
become_child function so that it can be directly called in the main
shell process performing the no-fork optimization.

Change Summary

Incremental Difference

--- yash/trunk/NEWS (revision 3968)
+++ yash/trunk/NEWS (revision 3969)
@@ -11,6 +11,8 @@
1111 Yash 2.49
1212
1313 * The "\e" escape sequence was not working in the "echo" built-in.
14+ * When a last command is a subshell, the parent shell's jobs were
15+ not being cleared when entering the subshell.
1416
1517 ----------------------------------------------------------------------
1618 Yash 2.48
--- yash/trunk/exec.c (revision 3968)
+++ yash/trunk/exec.c (revision 3969)
@@ -159,6 +159,7 @@
159159 __attribute__((nonnull));
160160 static inline void connect_pipes(pipeinfo_T *pi)
161161 __attribute__((nonnull));
162+static void become_child(bool leave);
162163 static void search_command(
163164 const char *restrict name, const wchar_t *restrict wname,
164165 commandinfo_T *restrict ci, enum srchcmdtype_T type)
@@ -799,7 +800,12 @@
799800 /* fork first if `type' is E_ASYNC, the command type is subshell,
800801 * or there is a pipe. */
801802 finally_exit = (type == E_SELF);
802- if (!finally_exit) {
803+ if (finally_exit) {
804+ if (c->c_type == CT_SUBSHELL)
805+ /* No command follows this subshell command, so we can execute the
806+ * subshell directly in this process. */
807+ become_child(false);
808+ } else {
803809 if (type == E_ASYNC || c->c_type == CT_SUBSHELL
804810 || pi->pi_fromprevfd >= 0 || pi->pi_tonextfds[PIPE_OUT] >= 0) {
805811 sigtype_T sigtype = (type == E_ASYNC) ? t_quitint : 0;
@@ -1026,23 +1032,30 @@
10261032 if (sigtype & t_tstp)
10271033 if (save_doing_job_control_now)
10281034 ignore_sigtstp();
1029- if (sigtype & t_leave) {
1030- clear_exit_trap();
1031- } else {
1032- phantomize_traps();
1033- neglect_all_jobs();
1035+ become_child(sigtype & t_leave); /* signal mask is restored here */
1036+ }
1037+ return cpid;
1038+}
1039+
1040+/* Resets traps, signal handlers, etc. for the current process to become a
1041+ * subshell. See `fork_and_reset' for the meaning of the `leave' argument. */
1042+void become_child(bool leave)
1043+{
1044+ if (leave) {
1045+ clear_exit_trap();
1046+ } else {
1047+ phantomize_traps();
1048+ neglect_all_jobs();
10341049 #if YASH_ENABLE_HISTORY
1035- close_history_file();
1050+ close_history_file();
10361051 #endif
1037- reset_execstate(true);
1038- }
1039- restore_signals(sigtype & t_leave); /* signal mask is restored here */
1040- clear_shellfds(sigtype & t_leave);
1041- is_interactive_now = false;
1042- suppresserrreturn = false;
1043- exitstatus = -1;
1052+ reset_execstate(true);
10441053 }
1045- return cpid;
1054+ restore_signals(leave); /* signal mask is restored here */
1055+ clear_shellfds(leave);
1056+ is_interactive_now = false;
1057+ suppresserrreturn = false;
1058+ exitstatus = -1;
10461059 }
10471060
10481061 /* Searches for a command.
Show on old repository browser