dc.tests: fix two test case to also depend on DC_BIG
[oweals/busybox.git] / docs / nofork_noexec.txt
index c58f5a83f139ef0fe78bcfff3f2f78a238df8f5c..9d210a1c9c6bac35d9db537f31c971f0f2eae9c6 100644 (file)
@@ -10,13 +10,8 @@ of reimplemented Unix commands, and we can do the same trick
 for speeding up busybox shells, and more. NOEXEC and NOFORK applets
 are exactly those applets which are eligible for these tricks.
 
-Applet will be subject to NOFORK/NOEXEC tricks if it is marked as such
-in applets.h. FEATURE_PREFER_APPLETS is a config option which
-globally enables usage of NOFORK/NOEXEC tricks.
-If it is enabled, FEATURE_SH_STANDALONE can be enabled too,
-and then shells will use NOFORK/NOEXEC tricks for ordinary commands.
-NB: shell builtins use these tricks regardless of FEATURE_SH_STANDALONE
-or FEATURE_PREFER_APPLETS.
+Applet will be subject to NOFORK/NOEXEC tricks only if it is marked
+as such in applets.src.h or in their inline "//applet:" directives.
 
 In C, if you want to call a program and wait for it, use
 spawn_and_wait(argv), BB_EXECVP(prog,argv) or BB_EXECLP(prog,argv0,...).
@@ -24,6 +19,31 @@ They check whether program name is an applet name and optionally
 do NOFORK/NOEXEC thing depending on configuration.
 
 
+       Relevant CONFIG options
+
+FEATURE_PREFER_APPLETS
+  Globally enables NOFORK/NOEXEC tricks for such programs as xargs
+  and find:
+  BB_EXECVP(cmd, argv) will try to exec /proc/self/exe
+  if command's name matches some applet name;
+  spawn_and_wait(argv) will do NOFORK/NOEXEC tricks
+
+//TODO: the above two things probably should have separate options?
+
+FEATURE_SH_STANDALONE
+  shells will try to exec /proc/self/exe if command's name matches
+  some applet name; shells will do NOEXEC trick on NOEXEC applets
+
+//TODO: split (same as for PREFER_APPLETS)
+
+FEATURE_SH_NOFORK
+  shells will do NOFORK trick on NOFORK applets
+
+NB: shell builtins use these tricks regardless of FEATURE_SH_STANDALONE,
+FEATURE_PREFER_APPLETS or FEATURE_SH_NOFORK. In effect, builtins
+are "always NOFORK".
+
+
        NOEXEC
 
 NOEXEC applet should work correctly if another applet forks and then
@@ -33,6 +53,7 @@ roughly are:
 * do not expect shared global variables/buffers to be in their
   "initialized" state. Examples: xfunc_error_retval can be != 1,
   bb_common_bufsiz1 can be scribbled over, ...
+  (although usually xfunc_error_retval's state is not a problem).
 * do not expect that stdio wasn't used before. Calling set[v]buf()
   can be disastrous.
 * ...
@@ -51,6 +72,9 @@ xargs, find, shells do it (grep for "spawn_and_wait" and
 This poses much more serious limitations on what applet can do:
 
 * all NOEXEC limitations apply.
+* do not run for a long time or wait for user input:
+  hush shell only handles signals (like ^C) after you return
+  from APPLET_main().
 * do not ever exit() or exec().
   - xfuncs are okay. They are using special trick to return
     to the caller applet instead of dying when they detect "x" condition.
@@ -60,15 +84,27 @@ This poses much more serious limitations on what applet can do:
 * do not use shared global data, or save/restore shared global data
   (e.g. bb_common_bufsiz1) prior to returning.
   - getopt32() is ok to use. You do not need to save/restore option_mask32,
-    it is already done by core code.
+    xfunc_error_retval, and logmode - it is already done by core code.
 * if you allocate memory, you can use xmalloc() only on the very first
   allocation. All other allocations should use malloc[_or_warn]().
   After first allocation, you cannot use any xfuncs.
   Otherwise, failing xfunc will return to caller applet
   without freeing malloced data!
-* All allocated data, opened files, signal handlers, termios settings,
-  O_NONBLOCK flags etc should be freed/closed/restored prior to return.
-* ...
+* the same applies to other resources, such as open fds: no xfuncs after
+  acquiring them!
+* All allocated data, opened files, signal handlers, termios settings
+  etc should be freed/closed/restored prior to return.
+
+Currently, ash shell signal handling is implemented in a way that signals
+have non-SA_RESTARTed handlers. This means that system calls can
+return EINTR. An example of such problem is "yes" applet:
+it is implemented so that it has a writing loop, this loop is exited on
+any write error, and in the case of user pressing ^C the error was EINTR.
+The problem is, the error causes stdout FILE* object to get into error
+state, needing clearerr() - or else subsequent shell output will also
+not work. ("yes" has been downgraded to NOEXEC, since hush signal handling
+does not have this problem - which makes "yes" to not exit on ^C (bug).
+But stray EINTRs can be seen in any NOFORK under ash, until ash is fixed).
 
 NOFORK applets give the most of speed advantage, but are trickiest
 to implement. In order to minimize amount of bugs and maintenance,
@@ -78,21 +114,30 @@ frequently executed from shell/find/xargs, particularly in shell
 script loops. Applets which mess with signal handlers, termios etc
 are probably not worth the effort.
 
+Applets which must be interruptible by ^C in shells can not be NOFORKs.
+
 Any NOFORK applet is also a NOEXEC applet.
 
 
-       Relevant CONFIG options
+       Calling NOFORK applets
 
-FEATURE_PREFER_APPLETS
-  BB_EXECVP(cmd, argv) will try to exec /proc/self/exe
-    if command's name matches some applet name
-  applet tables will contain NOFORK/NOEXEC bits
-  spawn_and_wait(argv) will do NOFORK/NOEXEC tricks
+API to call NOFORK applets is two functions:
 
-FEATURE_SH_STANDALONE (needs FEATURE_PREFER_APPLETS=y)
-  shells will try to exec /proc/self/exe if command's name matches
-    some applet name
-  shells will do NOEXEC trick on NOEXEC applets
+       run_nofork_applet(appno, argv)
+       spawn_and_wait(argv) // only if FEATURE_PREFER_APPLETS=y
 
-FEATURE_SH_NOFORK (needs FEATURE_PREFER_APPLETS=y)
-  shells will do NOFORK trick on NOFORK applets
+First one is directly used by shells if FEATURE_SH_NOFORK=y.
+Second one is used by many applets, but main users are xargs and find.
+It itself calls run_nofork_applet(), if argv[0] is a name
+of a NOFORK applet.
+
+run_nofork_applet() saves/inits/restores option parsing, xfunc_error_retval,
+logmode, applet_name. Thus, for example, caller does not need to worry about
+option_mask32 getting trashed.
+
+
+       Calling NOEXEC applets
+
+It's the same trusty spawn_and_wait(argv). If FEATURE_PREFER_APPLETS=y,
+it does NOEXEC trick. It resets xfunc_error_retval = 1 and
+logmode = LOGMODE_STDIO in the child.