Skip to content

child: refactor command execution to use goroutines with Pdeathsig#514

Merged
AkihiroSuda merged 2 commits into
rootless-containers:masterfrom
fahedouch:fix-Pdeathsig-behavior
Jun 12, 2025
Merged

child: refactor command execution to use goroutines with Pdeathsig#514
AkihiroSuda merged 2 commits into
rootless-containers:masterfrom
fahedouch:fix-Pdeathsig-behavior

Conversation

@fahedouch

@fahedouch fahedouch commented May 27, 2025

Copy link
Copy Markdown
Contributor

fixing #182

better controller for child Pdeathsig

@fahedouch
fahedouch force-pushed the fix-Pdeathsig-behavior branch from c75912c to 192bdb7 Compare May 27, 2025 21:12
@AkihiroSuda

Copy link
Copy Markdown
Member

Thanks, how to test this?

@AkihiroSuda AkihiroSuda modified the milestones: v2.3.5, v2.3.6 May 29, 2025
@fahedouch

Copy link
Copy Markdown
Contributor Author

you can test with the following script:

@#!/bin/bash

# Test script to verify Pdeathsig behavior using rootlesskit itself
# This script:
# 1. Uses rootlesskit to spawn a long-running process
# 2. Kills the rootlesskit parent process
# 3. Verifies that the child process is killed as expected

set -e

echo "Starting Pdeathsig test using rootlesskit..."

# Create a temporary directory for test artifacts
TEMP_DIR=$(mktemp -d)
echo "Created temporary directory: $TEMP_DIR"

# Create a marker file that will be touched by the child process if it's still alive
MARKER_FILE="$TEMP_DIR/child_still_alive"

# Create a script that will be executed by rootlesskit
CHILD_SCRIPT="$TEMP_DIR/child_script.sh"
cat > "$CHILD_SCRIPT" << 'EOF'
#!/bin/bash
echo "Child process started with PID: $$"
echo "Parent PID: $PPID"

# Register a trap to handle signals
trap 'echo "Child received signal, exiting"; exit 1' TERM INT

# Run for 30 seconds, checking if parent is still alive
for i in {1..30}; do
    echo "Child still running (iteration $i)..."
    
    # Check if parent has changed (died)
    CURRENT_PPID=$(ps -o ppid= -p $$)
    if [ "$CURRENT_PPID" != "$PPID" ]; then
        echo "Parent changed from $PPID to $CURRENT_PPID"
        if [ "$CURRENT_PPID" = "1" ]; then
            echo "Parent is now init (PID 1), parent has died"
            echo "Child should be killed by Pdeathsig, but if you see this message, it wasn't"
            touch MARKER_FILE_PLACEHOLDER
            exit 1
        fi
    fi
    
    sleep 1
done

# If we reach here, the child wasn't killed
echo "Child completed normally (this shouldn't happen if Pdeathsig is working)"
touch MARKER_FILE_PLACEHOLDER
EOF

# Replace the placeholder with the actual marker file path
sed -i "s|MARKER_FILE_PLACEHOLDER|$MARKER_FILE|g" "$CHILD_SCRIPT"
chmod +x "$CHILD_SCRIPT"

# Start rootlesskit with the child script
echo "Starting rootlesskit..."
rootlesskit "$CHILD_SCRIPT" &
ROOTLESSKIT_PID=$!
echo "Rootlesskit started with PID: $ROOTLESSKIT_PID"

# Wait a moment for the child to start
sleep 2

# Find the child process
CHILD_PID=$(pgrep -P $ROOTLESSKIT_PID)
if [ -z "$CHILD_PID" ]; then
    echo "Failed to find child process"
    exit 1
fi
echo "Found child process with PID: $CHILD_PID"

# Kill the rootlesskit process
echo "Killing rootlesskit process (PID: $ROOTLESSKIT_PID)..."
kill -9 $ROOTLESSKIT_PID

# Wait a moment for the child to be killed
sleep 2

# Check if the child process is still running
if ps -p $CHILD_PID > /dev/null; then
    echo "FAIL: Child process (PID: $CHILD_PID) is still running after parent was killed"
    kill -9 $CHILD_PID  # Clean up
    exit 1
else
    echo "PASS: Child process (PID: $CHILD_PID) was killed as expected"
fi

# Check if the marker file exists
if [ -f "$MARKER_FILE" ]; then
    echo "FAIL: Marker file exists, which means the child process wasn't killed by Pdeathsig"
    exit 1
else
    echo "PASS: Marker file doesn't exist, which means the child process was killed by Pdeathsig"
fi

echo "Test completed successfully!"
rm -rf "$TEMP_DIR"
exit 0

I can convert this script into integration test if needed.

@AkihiroSuda

Copy link
Copy Markdown
Member

integration test

Yes, please

- name: "Integration test: exit-code"
run: docker run --rm --privileged rootlesskit:test-integration ./integration-exit-code.sh
- name: "Integration test: propagation"
run: docker run --rm --privileged rootlesskit:test-integration ./integration-propagation.sh
- name: "Integration test: propagation (with `mount --make-rshared /`)"
run: docker run --rm --privileged rootlesskit:test-integration sh -exc "sudo mount --make-rshared / && ./integration-propagation.sh"
- name: "Integration test: restart"
run: docker run --rm --privileged rootlesskit:test-integration ./integration-restart.sh
- name: "Integration test: port"
# NOTE: "--net=host" is a bad hack to enable IPv6
run: docker run --rm --net=host --privileged rootlesskit:test-integration ./integration-port.sh
- name: "Integration test: IPv6 routing"
run: docker run --rm --privileged --sysctl net.ipv6.conf.all.disable_ipv6=0 rootlesskit:test-integration ./integration-ipv6.sh
- name: "Integration test: systemd socket activation"
run: docker run --rm --net=none --privileged rootlesskit:test-integration ./integration-systemd-socket.sh

Signed-off-by: fahed dorgaa <fahed.dorgaa@gmail.com>
@fahedouch
fahedouch force-pushed the fix-Pdeathsig-behavior branch from ece2f89 to cc4f3f5 Compare May 31, 2025 14:26
Comment thread hack/integration-pdeathsig.sh
@fahedouch fahedouch closed this May 31, 2025
@fahedouch fahedouch reopened this May 31, 2025
@fahedouch

Copy link
Copy Markdown
Contributor Author

The script works on the workstation but not in the CI environment; I suspect a timing issue.

…ion tests

Signed-off-by: fahed dorgaa <fahed.dorgaa@gmail.com>
@fahedouch

fahedouch commented Jun 1, 2025

Copy link
Copy Markdown
Contributor Author

@AkihiroSuda new changes are introduced:

  1. Modified child.go to ensure consistent Pdeathsig behavior regardless of reaper setting:

    • Added a goroutine with runtime.LockOSThread() for the non-reaper case (opt.Reaper is false)
    • Explicitly set Pdeathsig with unix.Prctl(unix.PR_SET_PDEATHSIG, uintptr(unix.SIGKILL), 0, 0, 0) in both cases
    • Created a new runWithoutReap() function to handle command execution without reaping
  2. Enhanced integration-pdeathsig.sh to:

    • Test both reaper settings (true and false) to verify consistent behavior

new changes ensure that child processes are properly terminated when the parent is killed with SIGKILL, regardless of whether the reaper functionality is enabled.

test fail not related to PR

@fahedouch
fahedouch requested a review from AkihiroSuda June 10, 2025 13:48

@AkihiroSuda AkihiroSuda left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@AkihiroSuda
AkihiroSuda merged commit 790f0e1 into rootless-containers:master Jun 12, 2025
9 of 10 checks passed
@AkihiroSuda

Copy link
Copy Markdown
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants