diff options
Diffstat (limited to 'recipes-containers/vcontainer')
4 files changed, 67 insertions, 17 deletions
diff --git a/recipes-containers/vcontainer/files/vcontainer-preinit.sh b/recipes-containers/vcontainer/files/vcontainer-preinit.sh index 7d4e7072..7c0fa590 100644 --- a/recipes-containers/vcontainer/files/vcontainer-preinit.sh +++ b/recipes-containers/vcontainer/files/vcontainer-preinit.sh | |||
| @@ -35,6 +35,10 @@ log() { | |||
| 35 | [ "$QUIET" = "0" ] && echo "$@" | 35 | [ "$QUIET" = "0" ] && echo "$@" |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | # Suppress kernel console messages in interactive mode so they don't | ||
| 39 | # pollute the terminal (loop device messages bypass loglevel=0) | ||
| 40 | [ "$QUIET" = "1" ] && { dmesg -n 1 2>/dev/null || true; } | ||
| 41 | |||
| 38 | log "=== vcontainer preinit (squashfs) ===" | 42 | log "=== vcontainer preinit (squashfs) ===" |
| 39 | 43 | ||
| 40 | # Wait for block devices to appear | 44 | # Wait for block devices to appear |
diff --git a/recipes-containers/vcontainer/files/vxn-init.sh b/recipes-containers/vcontainer/files/vxn-init.sh index 4b9b630a..c22fa8ea 100755 --- a/recipes-containers/vcontainer/files/vxn-init.sh +++ b/recipes-containers/vcontainer/files/vxn-init.sh | |||
| @@ -343,9 +343,10 @@ exec_in_container() { | |||
| 343 | if [ "$RUNTIME_INTERACTIVE" = "1" ]; then | 343 | if [ "$RUNTIME_INTERACTIVE" = "1" ]; then |
| 344 | # Interactive mode: connect stdin/stdout directly | 344 | # Interactive mode: connect stdin/stdout directly |
| 345 | export TERM=linux | 345 | export TERM=linux |
| 346 | printf '\r\033[K' | 346 | dmesg -n 1 2>/dev/null || true |
| 347 | echo "[vxn] chroot: $rootfs $cmd" > /dev/console 2>/dev/null | ||
| 347 | if [ "$use_sh" = "true" ]; then | 348 | if [ "$use_sh" = "true" ]; then |
| 348 | chroot "$rootfs" /bin/sh -c "cd '$workdir' 2>/dev/null; $cmd" | 349 | chroot "$rootfs" /bin/sh -c "cd '$workdir' 2>/dev/null; exec $cmd" |
| 349 | else | 350 | else |
| 350 | chroot "$rootfs" $cmd | 351 | chroot "$rootfs" $cmd |
| 351 | fi | 352 | fi |
| @@ -630,6 +631,13 @@ mount_base_filesystems | |||
| 630 | # Check for quiet boot mode | 631 | # Check for quiet boot mode |
| 631 | check_quiet_boot | 632 | check_quiet_boot |
| 632 | 633 | ||
| 634 | # Interactive mode: suppress kernel console messages early (before mounts | ||
| 635 | # that trigger loop device messages) and emit markers visible through PTY | ||
| 636 | if [ "$QUIET_BOOT" = "1" ]; then | ||
| 637 | dmesg -n 1 2>/dev/null || true | ||
| 638 | echo "[vxn] init" > /dev/console 2>/dev/null | ||
| 639 | fi | ||
| 640 | |||
| 633 | log "=== vxn Init ===" | 641 | log "=== vxn Init ===" |
| 634 | log "Version: $VCONTAINER_VERSION" | 642 | log "Version: $VCONTAINER_VERSION" |
| 635 | 643 | ||
| @@ -720,6 +728,7 @@ else | |||
| 720 | fi | 728 | fi |
| 721 | 729 | ||
| 722 | # Execute in container rootfs | 730 | # Execute in container rootfs |
| 731 | [ "$QUIET_BOOT" = "1" ] && echo "[vxn] exec: $EXEC_CMD" > /dev/console 2>/dev/null | ||
| 723 | exec_in_container "$CONTAINER_ROOT" "$EXEC_CMD" | 732 | exec_in_container "$CONTAINER_ROOT" "$EXEC_CMD" |
| 724 | fi | 733 | fi |
| 725 | 734 | ||
diff --git a/recipes-containers/vcontainer/files/vxn-oci-runtime b/recipes-containers/vcontainer/files/vxn-oci-runtime index 6158cddd..57144aea 100644 --- a/recipes-containers/vcontainer/files/vxn-oci-runtime +++ b/recipes-containers/vcontainer/files/vxn-oci-runtime | |||
| @@ -169,14 +169,6 @@ cmd_create() { | |||
| 169 | [ -f "$bundle/config.json" ] || die "create: $bundle/config.json not found" | 169 | [ -f "$bundle/config.json" ] || die "create: $bundle/config.json not found" |
| 170 | 170 | ||
| 171 | log "CREATE: id=$container_id bundle=$bundle console_socket=$console_socket" | 171 | log "CREATE: id=$container_id bundle=$bundle console_socket=$console_socket" |
| 172 | # Debug: log what the shim gives us | ||
| 173 | log " DEBUG: fd0=$(readlink /proc/$$/fd/0 2>/dev/null) fd1=$(readlink /proc/$$/fd/1 2>/dev/null) fd2=$(readlink /proc/$$/fd/2 2>/dev/null)" | ||
| 174 | log " DEBUG: bundle dir: $(ls -F $bundle/ 2>/dev/null | tr '\n' ' ')" | ||
| 175 | local _taskdir | ||
| 176 | _taskdir=$(dirname "$bundle") | ||
| 177 | log " DEBUG: task dir ($bundle): $(ls -F $bundle/ 2>/dev/null | tr '\n' ' ')" | ||
| 178 | log " DEBUG: parent dir ($_taskdir): $(ls -F $_taskdir/ 2>/dev/null | tr '\n' ' ')" | ||
| 179 | log " DEBUG: all pipes: $(find /run -type p 2>/dev/null | tr '\n' ' ')" | ||
| 180 | 172 | ||
| 181 | detect_arch | 173 | detect_arch |
| 182 | 174 | ||
| @@ -283,10 +275,17 @@ XENEOF | |||
| 283 | 275 | ||
| 284 | log " Domain $domname created (paused)" | 276 | log " Domain $domname created (paused)" |
| 285 | 277 | ||
| 286 | # Get domid and read Xen console PTY from xenstore | 278 | # Get domid and read Xen console PTY from xenstore. |
| 279 | # xenconsoled may not have created the PTY yet — wait for it. | ||
| 287 | local domid pty_path | 280 | local domid pty_path |
| 288 | domid=$(xl domid "$domname" 2>/dev/null) || die "create: failed to get domid for $domname" | 281 | domid=$(xl domid "$domname" 2>/dev/null) || die "create: failed to get domid for $domname" |
| 289 | pty_path=$(xenstore-read "/local/domain/$domid/console/tty" 2>/dev/null) || true | 282 | pty_path="" |
| 283 | local _try | ||
| 284 | for _try in 1 2 3 4 5 6 7 8 9 10; do | ||
| 285 | pty_path=$(xenstore-read "/local/domain/$domid/console/tty" 2>/dev/null) || true | ||
| 286 | [ -n "$pty_path" ] && break | ||
| 287 | sleep 0.5 | ||
| 288 | done | ||
| 290 | log " domid=$domid pty=$pty_path" | 289 | log " domid=$domid pty=$pty_path" |
| 291 | 290 | ||
| 292 | if [ -n "$pty_path" ]; then | 291 | if [ -n "$pty_path" ]; then |
| @@ -294,14 +293,32 @@ XENEOF | |||
| 294 | fi | 293 | fi |
| 295 | 294 | ||
| 296 | # Terminal mode: send PTY fd to shim via console-socket (SCM_RIGHTS) | 295 | # Terminal mode: send PTY fd to shim via console-socket (SCM_RIGHTS) |
| 296 | local sendtty_rc="-" | ||
| 297 | if [ -n "$console_socket" ] && [ -n "$pty_path" ]; then | 297 | if [ -n "$console_socket" ] && [ -n "$pty_path" ]; then |
| 298 | if command -v vxn-sendtty >/dev/null 2>&1; then | 298 | if command -v vxn-sendtty >/dev/null 2>&1; then |
| 299 | vxn-sendtty "$console_socket" "$pty_path" \ | 299 | vxn-sendtty "$console_socket" "$pty_path" |
| 300 | || log " WARNING: vxn-sendtty failed (socket=$console_socket pty=$pty_path)" | 300 | sendtty_rc=$? |
| 301 | log " Sent PTY fd to console-socket" | 301 | [ "$sendtty_rc" -ne 0 ] && log " WARNING: vxn-sendtty failed (rc=$sendtty_rc)" |
| 302 | log " Sent PTY fd to console-socket (rc=$sendtty_rc)" | ||
| 302 | else | 303 | else |
| 304 | sendtty_rc="missing" | ||
| 303 | log " WARNING: vxn-sendtty not found, cannot send PTY to shim" | 305 | log " WARNING: vxn-sendtty not found, cannot send PTY to shim" |
| 304 | fi | 306 | fi |
| 307 | elif [ -n "$console_socket" ] && [ -z "$pty_path" ]; then | ||
| 308 | sendtty_rc="no-pty" | ||
| 309 | log " WARNING: no PTY path from xenstore, cannot send to shim" | ||
| 310 | fi | ||
| 311 | |||
| 312 | # Write terminal debug to persistent storage (survives reboot) | ||
| 313 | if [ -n "$console_socket" ]; then | ||
| 314 | cat > /root/vxn-tty-debug 2>/dev/null <<DBGEOF | ||
| 315 | domid=$domid | ||
| 316 | pty=$pty_path | ||
| 317 | console_socket=$console_socket | ||
| 318 | sendtty_rc=$sendtty_rc | ||
| 319 | terminal=$terminal | ||
| 320 | domname=$domname | ||
| 321 | DBGEOF | ||
| 305 | fi | 322 | fi |
| 306 | 323 | ||
| 307 | # Persistent log dir — survives container deletion by shim | 324 | # Persistent log dir — survives container deletion by shim |
| @@ -349,8 +366,12 @@ XENEOF | |||
| 349 | done < "$_logdir/console.log" | 366 | done < "$_logdir/console.log" |
| 350 | fi | 367 | fi |
| 351 | else | 368 | else |
| 352 | # Terminal mode: shim owns PTY — just wait for domain death | 369 | # Terminal mode: shim owns PTY — just wait for domain death. |
| 353 | while xl list "$_dn" >/dev/null 2>&1; do sleep 2; done | 370 | # Close inherited stdout/stderr: go-runc captures runtime stdout |
| 371 | # via a pipe and cmd.Wait() blocks until EOF. If we hold the | ||
| 372 | # pipe's write end open, Create never returns to the shim. | ||
| 373 | exec >/dev/null 2>/dev/null | ||
| 374 | while xl list "$_dn" >/dev/null 2>&1; do sleep 0.5; done | ||
| 354 | fi | 375 | fi |
| 355 | ) & | 376 | ) & |
| 356 | local monitor_pid=$! | 377 | local monitor_pid=$! |
| @@ -627,6 +648,9 @@ done | |||
| 627 | command="${1:-}" | 648 | command="${1:-}" |
| 628 | shift || true | 649 | shift || true |
| 629 | 650 | ||
| 651 | # Log every invocation for debugging (before command dispatch) | ||
| 652 | log "INVOKE: cmd=$command args=$* root=$RUNTIME_ROOT" | ||
| 653 | |||
| 630 | case "$command" in | 654 | case "$command" in |
| 631 | create) cmd_create "$@" ;; | 655 | create) cmd_create "$@" ;; |
| 632 | start) cmd_start "$@" ;; | 656 | start) cmd_start "$@" ;; |
diff --git a/recipes-containers/vcontainer/files/vxn-sendtty.c b/recipes-containers/vcontainer/files/vxn-sendtty.c index a253b129..b1257100 100644 --- a/recipes-containers/vcontainer/files/vxn-sendtty.c +++ b/recipes-containers/vcontainer/files/vxn-sendtty.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <string.h> | 19 | #include <string.h> |
| 20 | #include <unistd.h> | 20 | #include <unistd.h> |
| 21 | #include <fcntl.h> | 21 | #include <fcntl.h> |
| 22 | #include <termios.h> | ||
| 22 | #include <sys/socket.h> | 23 | #include <sys/socket.h> |
| 23 | #include <sys/un.h> | 24 | #include <sys/un.h> |
| 24 | 25 | ||
| @@ -44,6 +45,18 @@ int main(int argc, char *argv[]) | |||
| 44 | return 1; | 45 | return 1; |
| 45 | } | 46 | } |
| 46 | 47 | ||
| 48 | /* Set PTY to raw mode for direct terminal I/O. | ||
| 49 | * Without this, the PTY slave's line discipline (echo, canonical mode) | ||
| 50 | * buffers input and echoes characters, preventing the shim from | ||
| 51 | * bridging the terminal correctly. */ | ||
| 52 | { | ||
| 53 | struct termios tio; | ||
| 54 | if (tcgetattr(pty_fd, &tio) == 0) { | ||
| 55 | cfmakeraw(&tio); | ||
| 56 | tcsetattr(pty_fd, TCSANOW, &tio); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 47 | sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); | 60 | sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); |
| 48 | if (sock_fd < 0) { | 61 | if (sock_fd < 0) { |
| 49 | perror("socket"); | 62 | perror("socket"); |
