blob: b45a4be89195d4771f09972e23f50cc52e96380e [file] [log] [blame]
Denis Vlasenko0d058362007-04-11 16:16:41 +00001 NOEXEC and NOFORK applets.
2
3Unix shells traditionally execute some commands internally in the attempt
4to dramatically speed up execution. It will be slow as hell if for every
Denis Vlasenkobcd5fc12008-01-06 06:27:17 +00005"echo blah" shell will fork and exec /bin/echo. To this end, shells
Denis Vlasenko0d058362007-04-11 16:16:41 +00006have to _reimplement_ these commands internally.
7
8Busybox is unique in this regard because it already is a collection
9of reimplemented Unix commands, and we can do the same trick
10for speeding up busybox shells, and more. NOEXEC and NOFORK applets
11are exactly those applets which are eligible for these tricks.
12
13Applet will be subject to NOFORK/NOEXEC tricks if it is marked as such
Denis Vlasenkobcd5fc12008-01-06 06:27:17 +000014in applets.h. FEATURE_PREFER_APPLETS is a config option which
Denis Vlasenko4b924f32007-05-30 00:29:55 +000015globally enables usage of NOFORK/NOEXEC tricks.
Denis Vlasenkobcd5fc12008-01-06 06:27:17 +000016If it is enabled, FEATURE_SH_STANDALONE can be enabled too,
17and then shells will use NOFORK/NOEXEC tricks for ordinary commands.
18NB: shell builtins use these tricks regardless of FEATURE_SH_STANDALONE
19or FEATURE_PREFER_APPLETS.
Denis Vlasenko0d058362007-04-11 16:16:41 +000020
Denis Vlasenkobcd5fc12008-01-06 06:27:17 +000021In C, if you want to call a program and wait for it, use
22spawn_and_wait(argv), BB_EXECVP(prog,argv) or BB_EXECLP(prog,argv0,...).
23They check whether program name is an applet name and optionally
24do NOFORK/NOEXEC thing depending on configuration.
Denis Vlasenko0d058362007-04-11 16:16:41 +000025
Denis Vlasenkobcd5fc12008-01-06 06:27:17 +000026
27 NOEXEC
Denis Vlasenko0d058362007-04-11 16:16:41 +000028
29NOEXEC applet should work correctly if another applet forks and then
30executes exit(<applet>_main(argc,argv)) in the child. The rules
31roughly are:
32
33* do not expect shared global variables/buffers to be in their
34 "initialized" state. Examples: xfunc_error_retval can be != 1,
35 bb_common_bufsiz1 can be scribbled over, ...
Denys Vlasenko06f20bf2017-01-26 00:27:53 +010036 (although usually xfunc_error_retval's state is not a problem).
Denis Vlasenko0d058362007-04-11 16:16:41 +000037* do not expect that stdio wasn't used before. Calling set[v]buf()
38 can be disastrous.
39* ...
40
41NOEXEC applets save only one half of fork+exec overhead.
Denis Vlasenkobcd5fc12008-01-06 06:27:17 +000042NOEXEC trick is disabled for NOMMU build.
Denis Vlasenko0d058362007-04-11 16:16:41 +000043
Denis Vlasenkobcd5fc12008-01-06 06:27:17 +000044
45 NOFORK
Denis Vlasenko0d058362007-04-11 16:16:41 +000046
47NOFORK applet should work correctly if another applet simply runs
Denys Vlasenkob72baeb2011-02-02 18:38:57 +010048<applet>_main(argc,argv) and then continues with its business.
49xargs, find, shells do it (grep for "spawn_and_wait" and
50"run_nofork_applet" to find more users).
51
52This poses much more serious limitations on what applet can do:
Denis Vlasenko0d058362007-04-11 16:16:41 +000053
54* all NOEXEC limitations apply.
Denys Vlasenko7c40ddd2017-08-02 16:37:39 +020055* do not run for a long time or wait for user input:
56 hush shell only handles signals (like ^C) after you return
57 from APPLET_main().
Denis Vlasenko0d058362007-04-11 16:16:41 +000058* do not ever exit() or exec().
59 - xfuncs are okay. They are using special trick to return
60 to the caller applet instead of dying when they detect "x" condition.
61 - you may "exit" to caller applet by calling xfunc_die(). Return value
62 is taken from xfunc_error_retval.
63 - fflush_stdout_and_exit(n) is ok to use.
64* do not use shared global data, or save/restore shared global data
Denys Vlasenkob72baeb2011-02-02 18:38:57 +010065 (e.g. bb_common_bufsiz1) prior to returning.
Denis Vlasenko0d058362007-04-11 16:16:41 +000066 - getopt32() is ok to use. You do not need to save/restore option_mask32,
Denys Vlasenko49e6bf22017-08-04 14:28:16 +020067 xfunc_error_retval, and logmode - it is already done by core code.
Denis Vlasenko0d058362007-04-11 16:16:41 +000068* if you allocate memory, you can use xmalloc() only on the very first
69 allocation. All other allocations should use malloc[_or_warn]().
70 After first allocation, you cannot use any xfuncs.
Denis Vlasenkobcd5fc12008-01-06 06:27:17 +000071 Otherwise, failing xfunc will return to caller applet
72 without freeing malloced data!
Denys Vlasenko49e6bf22017-08-04 14:28:16 +020073* the same applies to other resources, such as open fds: no xfuncs after
74 acquiring them!
75* All allocated data, opened files, signal handlers, termios settings
76 etc should be freed/closed/restored prior to return.
77
78Currently, ash shell signal handling is implemented in a way that signals
79have non-SA_RESTARTed handlers. This means that system calls can
80return EINTR. An example of such problem is "yes" applet:
81it is implemented so that it has a writing loop, this loop is exited on
82any write error, and in the case of user pressing ^C the error was EINTR.
83The problem is, the error causes stdout FILE* object to get into error
84state, needing clearerr() - or else subsequent shell output will also
85not work. ("yes" has been downgraded to NOEXEC, since hush signal handling
86does not have this problem - which makes "yes" to not exit on ^C (bug).
87But stray EINTRs can be seen in any NOFORK under ash, until ash is fixed).
Denis Vlasenko0d058362007-04-11 16:16:41 +000088
89NOFORK applets give the most of speed advantage, but are trickiest
90to implement. In order to minimize amount of bugs and maintenance,
91prime candidates for NOFORK-ification are those applets which
92are small and easy to audit, and those which are more likely to be
93frequently executed from shell/find/xargs, particularly in shell
94script loops. Applets which mess with signal handlers, termios etc
95are probably not worth the effort.
96
Denys Vlasenko49e6bf22017-08-04 14:28:16 +020097Applets which must be interruptible by ^C in shells can not be NOFORKs.
98
Denis Vlasenko0d058362007-04-11 16:16:41 +000099Any NOFORK applet is also a NOEXEC applet.
Denys Vlasenkob72baeb2011-02-02 18:38:57 +0100100
101
Denys Vlasenko06f20bf2017-01-26 00:27:53 +0100102 Calling NOFORK applets
103
104API to call NOFORK applets is two functions:
105
106 run_nofork_applet(appno, argv)
107 spawn_and_wait(argv) // only if FEATURE_PREFER_APPLETS=y
108
109First one is directly used by shells if FEATURE_SH_NOFORK=y.
110Second one is used by many applets, but main users are xargs and find.
Denys Vlasenko49e6bf22017-08-04 14:28:16 +0200111It itself calls run_nofork_applet(), if argv[0] is a name
Denys Vlasenko06f20bf2017-01-26 00:27:53 +0100112of a NOFORK applet.
113
114run_nofork_applet() saves/inits/restores option parsing, xfunc_error_retval,
Denys Vlasenko39194f02017-08-03 19:00:01 +0200115logmode, applet_name. Thus, for example, caller does not need to worry about
Denys Vlasenko06f20bf2017-01-26 00:27:53 +0100116option_mask32 getting trashed.
117
118
Denys Vlasenko9967c992017-01-26 01:13:58 +0100119 Calling NOEXEC applets
120
121It's the same trusty spawn_and_wait(argv). If FEATURE_PREFER_APPLETS=y,
122it does NOEXEC trick. It resets xfunc_error_retval = 1 and
123logmode = LOGMODE_STDIO in the child.
124
125
Denys Vlasenkob72baeb2011-02-02 18:38:57 +0100126 Relevant CONFIG options
127
128FEATURE_PREFER_APPLETS
129 BB_EXECVP(cmd, argv) will try to exec /proc/self/exe
Denys Vlasenko06f20bf2017-01-26 00:27:53 +0100130 if command's name matches some applet name;
Denys Vlasenkob72baeb2011-02-02 18:38:57 +0100131 spawn_and_wait(argv) will do NOFORK/NOEXEC tricks
132
Denys Vlasenko06f20bf2017-01-26 00:27:53 +0100133//TODO: the above two things probably should have separate options?
Denys Vlasenkob72baeb2011-02-02 18:38:57 +0100134
Denys Vlasenko06f20bf2017-01-26 00:27:53 +0100135FEATURE_SH_STANDALONE
136 shells will try to exec /proc/self/exe if command's name matches
137 some applet name; shells will do NOEXEC trick on NOEXEC applets
138
139//TODO: split (same as for PREFER_APPLETS)
140
141FEATURE_SH_NOFORK
Denys Vlasenkob72baeb2011-02-02 18:38:57 +0100142 shells will do NOFORK trick on NOFORK applets