Fix #38: Add --enable-emergency-shell fallback debug mode

This patch adds a very special debug mode to Finit.  With this feature
enabled the actual duties of PID 1 is forked off early to a child.  If
that child ever dies, usually due to a SIGSEGV, this wakes up the real
PID 1 which lauches a debug shell on the console.

Remember to disable 'quiet' and enable '--debug' on the kernel command
line to get all the debug logs -- which these days goes into the kernel
log in /dev/kmsg -- simply `cat /dev/kmsg` and use Ctrl-C to get the
shell prompt back.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson
2016-09-04 20:27:12 +02:00
parent 79207dcb22
commit 3ca28e765d
2 changed files with 40 additions and 0 deletions
+7
View File
@@ -37,6 +37,10 @@ PKG_CHECK_MODULES([uev], [libuev >= 1.4.0])
PKG_CHECK_MODULES([lite], [libite >= 1.5.0])
# Check for configured Finit features
AC_ARG_ENABLE(emergency_shell,
AS_HELP_STRING([--enable-emergency-shell], [Experimental emergency fallback at boot.
Only use this for debugging very early boot problems with Finit.]))
AC_ARG_ENABLE(rw-rootfs,
AS_HELP_STRING([--enable-rw-rootfs], [Remount / R/W at boot, usually not for embedded]))
@@ -117,6 +121,9 @@ AC_ARG_WITH(random-seed,
### Enable features ###########################################################################
# Create config.h from selected features and fallback defautls
AS_IF([test "x$enable_emergency_shell" = "xyes"], [
AC_DEFINE(EMERGENCY_SHELL, 1, [Fork off init and let PID 1 wait and start /bin/sh if init crashes.])])
AS_IF([test "x$enable_rw_rootfs" = "xyes"], [
AC_DEFINE(REMOUNT_ROOTFS, 1, [Remount / as rw at boot])])
+33
View File
@@ -33,6 +33,7 @@
#include <mntent.h>
#include <sys/mount.h>
#include <sys/stat.h> /* umask(), mkdir() */
#include <sys/wait.h>
#include <lite/lite.h>
#include "finit.h"
@@ -202,6 +203,33 @@ static int fismnt(char *dir)
return found;
}
/*
* If everything goes south we can use this to give the operator an
* emergency shell to debug the problem -- Finit should not crash!
*/
static void emergency_shell(void)
{
#ifdef EMERGENCY_SHELL
pid_t pid;
pid = fork();
if (pid) {
waitpid(pid, NULL, 0);
fprintf(stderr, "\n=> Embarrassingly, Finit has crashed. Check /dev/kmsg for details.\n");
fprintf(stderr, "=> For more, remove 'quiet' and add '--debug' to the kernel command line.\n\n");
/*
* Become session leader and set controlling TTY
* to enable Ctrl-C and job control in shell.
*/
setsid();
ioctl(STDIN_FILENO, TIOCSCTTY, 1);
execl(_PATH_BSHELL, _PATH_BSHELL, NULL);
}
#endif /* EMERGENCY_SHELL */
}
int main(int argc, char* argv[])
{
int err;
@@ -215,6 +243,11 @@ int main(int argc, char* argv[])
if (getpid() != 1)
return client(argc, argv);
/*
* In case of emergency.
*/
emergency_shell();
/*
* Hello world.
*/