We do this by maintaining a mask (for each pid) giving the fds to be closed on exec. We wrap functions that close fds so that their close-on-exec bits can be cleared at that point.
This implementation may close the fds even if the execve operation ultimately fails.
Also, fix issue where callers of getopt32() weren't properly detecting errors on GNO due to a size mismatch.
This avoids strange behavior when commands using getopt32 (like export) are invoked multiple times, sometimes with invalid arguments.
This avoids problems stemming from the fact that GNO's environment implementation may deallocate those strings, in some cases before we're done with them. It also allows us to uppercase the variable names, although since we made them case-insensitive this only matters for display purposes (in "set" output).
This avoids a problem where one of the SIGALRM signals could be delivered after the original SIGALRM handler was restored, which would normally cause the process to terminate.
For now, we just rely on polling in a loop to determine when the child is done. This isn't optimal, but should be OK. If procsend() worked, we could use that in the child to signal the parent. However, procsend() is broken in GNO 2.0.6 -- it seems that it actually tries to invoke the send() call for sockets, but with the wrong arguments, leading to a crash.
Busybox already uses sendfile in httpd. This patch proposes to use it
globally to copy data between file descriptors.
It speeds up the copying on slow systems a lot - below are the times needed
to copy a 450Mb file with and without this option enabled on a BeagleBone
Black:
sendfile:
user 0m0.000s
sys 0m8.170s
read/write 4k:
user 0m0.470s
sys 0m16.300s
function old new delta
bb_full_fd_action 394 474 +80
Signed-off-by: Bartosz Golaszewski <bartekgola@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Sometimes ARG_MAX is small (like 32k) yet sysconf(_SC_ARG_MAX)
is big, and people prefer using the bigger value.
OTOH, with sufficiently large ARG_MAX, further wins from
sysconf(_SC_ARG_MAX) being bigger are exponentially smaller:
you can see 4 times fewer fork+execs when you run find, but
when each execed process already takes a thousand parameters
it's likely execution time is dominated by what that process
does with each parameter.
Thus, with this change ARG_MAX is used if it's sufficiently big,
otherwise sysconf(_SC_ARG_MAX) is used.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This should allow most typical cases of arguments with spaces to work correctly, although it will still break down in some cases. We can't do this perfectly, because we're ultimately dependent on the argument parsing code in the target application, and at least the code generated by ORCA/C doesn't give us a way to make an arbitrary string be treated as a single argument.
*Most significantly, we avoid using setpgid(), because it doesn't work and in fact corrupts the kernel's process group table.
*Also, work around tctpgrp() returning garbage instead of 0 on success.
This adds an implementation of tcsetpgrp that works by reading the process tables to find a process in the appropriate group. This isn't used for the main job control operations, though, since it might be relatively slow.
At this point, basic job control seems to work.
* Push/pop environment to make sure it is isolated from our parents and children.
* Make all environment vars (and shell vars) case-insensitive, consistent with GNO's internal handling of environment vars.
* Wrap putenv and unsetenv to make sure they are called with lower-case variable names, which is necessary to maintain consistency between the environ array and the kernel's internal representation of variables.
The version in libc both matches things it shouldn't and doesn't match things it should, in (at least) cases where a pattern includes additional stuff beyond a *.
This should avoid strange behavior due to races when the parent has resumed but the child is still running the exec* code in libc, which mainly manifests itself when running at low speed.
We also change to signaling the child's completion with SIGALRM, and setting an extra alarm in the parent in case the child doesn't actually do it.
GNO's _exit (contrary to its man page) does clean-up for stuff like the memory allocator, which is inappropriate in a forked child process and leads to hangs and crashes.