github.com/containers/podman/v5@v5.1.0-rc1/test/system/130-kill.bats (about)

     1  #!/usr/bin/env bats   -*- bats -*-
     2  #
     3  # tests for podman kill
     4  #
     5  
     6  load helpers
     7  
     8  # bats test_tags=distro-integration
     9  @test "podman kill - test signal handling in containers" {
    10  
    11      # Prepare for 'logs -f'
    12      run_podman info --format '{{.Host.LogDriver}}'
    13      log_driver=$output
    14      run_podman info --format '{{.Host.EventLogger}}'
    15      event_logger=$output
    16      opt_log_driver=
    17      if [ $log_driver = "journald" ] && [ $event_logger != "journald" ]; then
    18          # Since PR#10431, 'logs -f' with journald driver is only supported with journald events backend.
    19          # Set '--log driver' temporally because remote doesn't support '--events-backend'.
    20          opt_log_driver="--log-driver k8s-file"
    21      fi
    22  
    23      # Start a container that will handle all signals by emitting 'got: N'
    24      local -a signals=(1 2 3 4 5 6 8 10 12 13 14 15 16 20 21 22 23 24 25 26 64)
    25      run_podman run -d ${opt_log_driver} $IMAGE sh -c \
    26          "for i in ${signals[*]}; do trap \"echo got: \$i\" \$i; done;
    27          echo READY;
    28          while ! test -e /stop; do sleep 0.1; done;
    29          echo DONE"
    30      cid="$output"
    31  
    32      # Run 'logs -f' on that container, but run it in the background with
    33      # redirection to a named pipe from which we (foreground job) read
    34      # and confirm that signals are received. We can't use run_podman here.
    35      local fifo=${PODMAN_TMPDIR}/podman-kill-fifo.$(random_string 10)
    36      mkfifo $fifo
    37      $PODMAN logs -f $cid >$fifo </dev/null &
    38      podman_log_pid=$!
    39  
    40      # Open the FIFO for reading, and keep it open. This prevents a race
    41      # condition in which the container can exit (e.g. if for some reason
    42      # it doesn't handle the signal) and we (this test) try to read from
    43      # the FIFO. Since there wouldn't be an active writer, the open()
    44      # would hang forever. With this exec we keep the FD open, allowing
    45      # 'read -t' to time out and report a useful error.
    46      exec 5<$fifo
    47  
    48      # First container emits READY when ready; wait for it.
    49      read -t 60 -u 5 ready
    50      is "$ready" "READY" "first log message from container"
    51  
    52      # Helper function: send the given signal, verify that it's received.
    53      kill_and_check() {
    54          local signal=$1
    55          local signum=${2:-$1}       # e.g. if signal=HUP, we expect to see '1'
    56  
    57          run_podman kill -s $signal $cid
    58          read -t 60 -u 5 actual || die "Timed out: no ACK for kill -s $signal"
    59          is "$actual" "got: $signum" "Signal $signal handled by container"
    60      }
    61  
    62      # Send signals in random order; make sure each one is received
    63      for s in $(fmt --width=2 <<< "${signals[*]}" | sort --random-sort);do
    64          kill_and_check $s
    65      done
    66  
    67      # Variations: with leading dash; by name, with/without dash or SIG
    68      kill_and_check -1        1
    69      kill_and_check -INT      2
    70      kill_and_check  FPE      8
    71      kill_and_check -SIGUSR1 10
    72      kill_and_check  SIGUSR2 12
    73  
    74      # Done. Tell the container to stop, and wait for final DONE.
    75      # The '-d' is because container exit is racy: the exec process itself
    76      # could get caught and killed by cleanup, causing this step to exit 137
    77      run_podman exec -d $cid touch /stop
    78      read -t 5 -u 5 done || die "Timed out waiting for DONE from container"
    79      is "$done" "DONE" "final log message from container"
    80  
    81      # Clean up
    82      run_podman wait $cid
    83      run_podman rm $cid
    84      wait $podman_log_pid
    85  }
    86  
    87  @test "podman kill - rejects invalid args" {
    88      # These errors are thrown by the imported docker/signal.ParseSignal()
    89      local -a bad_signal_names=(0 SIGBADSIG SIG BADSIG %% ! "''" '""' " ")
    90      for s in ${bad_signal_names[@]}; do
    91          # 'nosuchcontainer' is fine: podman should bail before it gets there
    92          run_podman 125 kill -s $s nosuchcontainer
    93          is "$output" "Error: invalid signal: $s" "Error from kill -s $s"
    94  
    95          run_podman 125 pod kill -s $s nosuchpod
    96          is "$output" "Error: invalid signal: $s" "Error from pod kill -s $s"
    97      done
    98  
    99      # Special case: these too are thrown by docker/signal.ParseSignal(),
   100      # but the dash sign is stripped by our wrapper in utils, so the
   101      # error message doesn't include the dash.
   102      local -a bad_dash_signals=(-0 -SIGBADSIG -SIG -BADSIG -)
   103      for s in ${bad_dash_signals[@]}; do
   104          run_podman 125 kill -s $s nosuchcontainer
   105          is "$output" "Error: invalid signal: ${s##-}" "Error from kill -s $s"
   106      done
   107  
   108      # This error (signal out of range) is thrown by our wrapper
   109      local -a bad_signal_nums=(65 -65 96 999 99999999)
   110      for s in ${bad_signal_nums[@]}; do
   111          run_podman 125 kill -s $s nosuchcontainer
   112          is "$output" "Error: valid signals are 1 through 64" \
   113             "Error from kill -s $s"
   114      done
   115  
   116      # 'podman create' uses the same parsing code
   117      run_podman 125 create --stop-signal=99 $IMAGE
   118      is "$output" "Error: valid signals are 1 through 64" "podman create"
   119  }
   120  
   121  @test "podman kill - print IDs or raw input" {
   122      # kill -a must print the IDs
   123      run_podman run --rm -d $IMAGE top
   124      ctrID="$output"
   125      run_podman kill -a
   126      is "$output" "$ctrID"
   127  
   128      # kill $input must print $input
   129      cname=$(random_string)
   130      run_podman run --rm -d --name $cname $IMAGE top
   131      run_podman kill $cname
   132      is "$output" $cname
   133  }
   134  
   135  @test "podman kill - concurrent stop" {
   136      # 14761 - concurrent kill/stop must record the exit code
   137      random_name=$(random_string 10)
   138      run_podman run -d --replace --name=$random_name $IMAGE sh -c "trap 'echo Received SIGTERM, ignoring' SIGTERM; echo READY; while :; do sleep 0.2; done"
   139      $PODMAN stop -t 1 $random_name &
   140      run_podman kill $random_name
   141      run_podman wait $random_name
   142      run_podman rm -f $random_name
   143  }
   144  
   145  @test "podman wait - exit codes" {
   146      random_name=$(random_string 10)
   147      run_podman create --name=$random_name $IMAGE /no/such/command
   148      run_podman container inspect  --format "{{.State.StoppedByUser}}" $random_name
   149      is "$output" "false" "container not marked to be stopped by a user"
   150      # Container never ran -> exit code == 0
   151      run_podman wait $random_name
   152      # Container did not start successfully -> exit code != 0
   153      run_podman 125 start $random_name
   154      # FIXME(#14873): while older Podmans return 0 on wait, Docker does not.
   155      run_podman wait $random_name
   156  }
   157  
   158  @test "podman kill - no restart" {
   159      ctr=$(random_string 10)
   160      run_podman run -d --restart=always --name=$ctr $IMAGE \
   161          sh -c "trap 'exit 42' SIGTERM; echo READY; while :; do sleep 0.2; done"
   162      run_podman container inspect  --format "{{.State.Status}}" $ctr
   163      is "$output" "running" "make sure container is running"
   164      # Send SIGTERM and make sure the container exits.
   165      run_podman kill -s=TERM $ctr
   166      run_podman wait $ctr
   167      is "$output" "42" "container exits with 42 on receiving SIGTERM"
   168      run_podman container inspect  --format "{{.State.StoppedByUser}}" $ctr
   169      is "$output" "true" "container is marked to be stopped by a user"
   170  }
   171  
   172  # vim: filetype=sh