ash: INT_OFF/INT_ON around run_nofork_applet()
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 4 Aug 2017 12:50:03 +0000 (14:50 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 4 Aug 2017 12:50:03 +0000 (14:50 +0200)
function                                             old     new   delta
evalcommand                                         1441    1447      +6

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash.c

index ca9926b548793ed28b88a4f26c5eb31046769169..2afa5e83d76f364b49283ec3242c204bf7718c4a 100644 (file)
@@ -9919,10 +9919,26 @@ evalcommand(union node *cmd, int flags)
                int applet_no = (- cmdentry.u.index - 2);
                if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
                        listsetvar(varlist.list, VEXPORT|VSTACK);
-                       /* run <applet>_main() */
-//FIXME: do we need INT_OFF / INT_ON here?
-//wouldn't open files and allocations leak on ^C otherwise?
+                       /*
+                        * Run <applet>_main().
+                        * Signals (^C) can't interrupt here.
+                        * Otherwise we can mangle stdio or malloc internal state.
+                        * This makes applets which can run for a long time
+                        * and/or wait for user input ineligible for NOFORK:
+                        * for example, "yes" or "rm" (rm -i waits for input).
+                        */
+                       INT_OFF;
                        status = run_nofork_applet(applet_no, argv);
+                       /*
+                        * Try enabling NOFORK for "yes" applet.
+                        * ^C _will_ stop it (write returns EINTR),
+                        * but this causes stdout FILE to be stuck
+                        * and needing clearerr(). What if other applets
+                        * also can get EINTRs? Do we need to switch
+                        * our signals to SA_RESTART?
+                        */
+                       /*clearerr(stdout);*/
+                       INT_ON;
                        break;
                }
 #endif