On Fri, Aug 15, 2008 at 10:55:34PM +0200, Jérémy Bobbio wrote: > On Sat, Aug 09, 2008 at 06:19:09PM +0200, Frans Pop wrote: > > On Wednesday 06 August 2008, Jérémy Bobbio wrote: > > I think someone should look into the option of starting udevd _before_ we > > run init (as also suggested by Marco in a recent discussion on IRC). > > Attached is a patch the implements this. Details inside. > > Attached is also a patch against udev that simple moves > /lib/debian-installer-startup.d/S02udev to > /lib/debian-installer/start-udev so the script can be called from the > init script. Ok, I have spent more time working on this and I think that there might be a good chance that this would be the last time. Bastian Blank suggested on IRC when we discussed the proposed fix against busybox (see #493865) to replace cttyhack with a custom solution. I have digged the kernel source code, made several false starts, but the attached patch contain a solution that should work in any cases. It is based on the previous patch that make udev starts earlier. More details inside. Please have a look, I have quite some faith in this approach. Cheers, -- Jérémy Bobbio .''`. lunar@debian.org : :Ⓐ : # apt-get install anarchism `. `'` `-
commit 02f46f59a160ced45df3b9bcc9ce54175627e6b8 Author: Jérémy Bobbio <lunar@debian.org> Date: Sat Aug 23 20:59:30 2008 +0200 Rework the switch from /dev/console to the real console device As cttyhack is not compatible with console devices other than ttySx, let's replace replace it with a custom solution. A new shell sript is introduced in rootskel, /sbin/reopen-console. As there is no proper way to retrieve the "selected console" from the kernel, this script tries to redo the kernel logic internally by doing the following: 1. Parse kernel messages to find which consoles have been enabled. 2. If there is only one console, use it. If there is a "handover" message, use the "real" console. 3. Parse the kernel command-line to find the last "console=" option that matches one of the enabled console. 4. If nothing was found, default to /dev/console as a safety net. This script then exec() a small binary, /sbin/steal-ctty, that will open the device found, mangle the file descriptors and claim the ctty. Once done, another exec() will finally execute the arguments given to /bin/reopen-console. cttyhack was previously used in /etc/inittab for both /sbin/debian-installer-startup and /sbin/debian-installer. To get rid of this small redundancy, reopen-console is called directly in /init. As this process now uses far more file descriptors, the previous numbers assigned for extra file descriptors in cdebconf was reached when starting graphical installations. These have been increased in order to solve that issue. (Closes: #484366) diff --git a/packages/cdebconf/debian/changelog b/packages/cdebconf/debian/changelog index 9574a68..09e1ad8 100644 --- a/packages/cdebconf/debian/changelog +++ b/packages/cdebconf/debian/changelog @@ -7,6 +7,9 @@ cdebconf (0.134) UNRELEASED; urgency=low (Closes: #487691) * Use a dynamically allocated rope in strexpand(). (Closes: #496093) + * Increase extra fd numbers by 30 in confmodule_run(). + This is necessary as the new method of switching from /dev/console to the + real device open more file descriptors in the process space. [ Colin Watson ] * When receiving a new template with DATA, ensure that the corresponding diff --git a/packages/cdebconf/src/confmodule.c b/packages/cdebconf/src/confmodule.c index 66eb13c..19f89c3 100644 --- a/packages/cdebconf/src/confmodule.c +++ b/packages/cdebconf/src/confmodule.c @@ -181,15 +181,15 @@ static pid_t confmodule_run(struct confmodule *mod, int argc, char **argv) DIE("Cannot execute client config script"); break; case 0: - /* 20=read/to, 21=write/to, 22=read/from, 23=write/from, 24=null */ + /* 50=read/to, 51=write/to, 52=read/from, 53=write/from, 54=null */ config[4] = open("/dev/null", O_RDWR); for (i = 0; i < 5; i++) - check_fd(config[i], 20 + i, old); + check_fd(config[i], 50 + i, old); for (i = 0; i <= 2; i++) - dup2(old[i] ? i : 24, DEBCONF_OLD_FD_BASE + i); - dup2(20, 0); dup2(23, 1); dup2(23, 3); + dup2(old[i] ? i : 54, DEBCONF_OLD_FD_BASE + i); + dup2(50, 0); dup2(53, 1); dup2(53, 3); for (i = 0; i < 5; i++) - close(20 + i); + close(50 + i); args = (char **)malloc(sizeof(char *) * argc); for (i = 1; i < argc; i++) diff --git a/packages/rootskel/debian/changelog b/packages/rootskel/debian/changelog index 32532c2..838411f 100644 --- a/packages/rootskel/debian/changelog +++ b/packages/rootskel/debian/changelog @@ -12,6 +12,9 @@ rootskel (1.65) UNRELEASED; urgency=low [ Jérémy Bobbio ] * Start udev before running init. Depends: udev-udeb (>= 0.125-6) + * Rework the switch from /dev/console to the real console device + (e.g. /dev/tty0). (Closes: #484366) + Breaks: cdebconf-gtk-udeb (<< 0.134) -- Colin Watson <cjwatson@debian.org> Tue, 29 Jul 2008 17:24:58 +0100 diff --git a/packages/rootskel/src/etc/inittab b/packages/rootskel/src/etc/inittab index 8aef38f..a2a2421 100644 --- a/packages/rootskel/src/etc/inittab +++ b/packages/rootskel/src/etc/inittab @@ -2,10 +2,10 @@ # busybox init configuration for debian-installer # main rc script -::sysinit:/bin/cttyhack /sbin/debian-installer-startup +::sysinit:/sbin/debian-installer-startup # main setup program -::respawn:/bin/cttyhack /sbin/debian-installer +::respawn:/sbin/debian-installer # convenience shells tty2::askfirst:-/bin/sh diff --git a/packages/rootskel/src/init b/packages/rootskel/src/init index 0a05b25..c8567b4 100755 --- a/packages/rootskel/src/init +++ b/packages/rootskel/src/init @@ -8,7 +8,7 @@ mount /proc mount /sys /lib/debian-installer/start-udev -init='busybox init' +init='/bin/busybox init' for i in $(cat /proc/cmdline); do case $i in init=*) @@ -17,4 +17,4 @@ for i in $(cat /proc/cmdline); do esac done debugshell "before init" -exec $init +exec /sbin/reopen-console $init diff --git a/packages/rootskel/src/sbin/Makefile b/packages/rootskel/src/sbin/Makefile index d6c072e..b5e374e 100644 --- a/packages/rootskel/src/sbin/Makefile +++ b/packages/rootskel/src/sbin/Makefile @@ -4,6 +4,16 @@ files_exec = \ debian-installer \ debian-installer-startup \ shutdown \ - init + init \ + reopen-console \ + steal-ctty + +steal-ctty: steal-ctty.c + gcc -Os -Wall steal-ctty.c -o steal-ctty + +build: steal-ctty + +clean: + rm -f steal-ctty include ../../Makefile.inc diff --git a/packages/rootskel/src/sbin/reopen-console b/packages/rootskel/src/sbin/reopen-console new file mode 100644 index 0000000..b4bbe81 --- /dev/null +++ b/packages/rootskel/src/sbin/reopen-console @@ -0,0 +1,40 @@ +#!/bin/sh + +# In order to give proper access to the tty, we need to locate the device +# corresponding to the console we are actually using. + +# If the kernel emitted an "handover" message, then it's the one +console="$(dmesg -s 65535 | + sed -n -e 's/.*\] console handover: boot \[.*\] -> real \[\(.*\)\]$/\1/p')" + +if [ -z "$console" ]; then + # Retrieve all enabled consoles from boot log + consoles="$(dmesg -s 65535 | + sed -n -e 's/.*\] console \[\(.*\)\] enabled/\1/p')" + # Only one console? Then we are good. + if [ $(echo "$consoles" | wc -l) -eq 1 ]; then + console="$consoles" + fi +fi + +if [ -z "$console" ]; then + # Locate the last enabled console present on the command line + for arg in $(cat /proc/cmdline); do + case $arg in + console=*) + arg=${arg#console=} + if echo "$consoles" | grep -q "^${arg%%,*}$"; then + console=${arg%%,*} + fi + ;; + esac + done +fi + +if [ -z "$console" ]; then + # Still nothing? Default to /dev/console for safety + console=console +fi + +# Some other session may have it as ctty. Steal it from them +exec /sbin/steal-ctty /dev/$console "$@" diff --git a/packages/rootskel/src/sbin/steal-ctty.c b/packages/rootskel/src/sbin/steal-ctty.c new file mode 100644 index 0000000..93ad3bc --- /dev/null +++ b/packages/rootskel/src/sbin/steal-ctty.c @@ -0,0 +1,25 @@ +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +int main(int argc, char ** argv) +{ + int fd; + + if (-1 == (fd = open(argv[1], O_RDWR))) { + perror("steal-ctty"); + return 1; + } + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + while (fd > 2) { + close(fd--); + } + ioctl(0, TIOCSCTTY, (char *) 1); + execvp(argv[2], &argv[2]); + /* never reached. */ + return 0; +}
Attachment:
signature.asc
Description: Digital signature