| #!/bin/sh |
| |
| # Copyright 2016 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| JOB=$(basename "$0") |
| |
| bootstat ui-post-stop |
| set +e |
| . /sbin/killers |
| |
| # Terminate PKCS #11 services. |
| cryptohome --action=pkcs11_terminate |
| |
| # Thaw any renderers that may have been left behind. If we |
| # have crashed while renderers are frozen, they'll be unkillable |
| # until we do this. |
| echo "THAWED" > "${CHROME_FREEZER_CGROUP_DIR}/to_be_frozen/freezer.state" |
| |
| # Terminate any processes with files open on the mount point |
| # TODO(wad) parallelize with VFS/PID namespaces. |
| kill_with_open_files_on_path_and_mountpoints \ |
| '/home/[^.]|/data|/home/.shadow/[a-fA-F0-9]{40}/mount' "cryptohome" \ |
| /home/chronos/u-* |
| |
| # Make sure everything is going down. No exceptions. |
| # The loop is so that clever daemons can't evade the kill by |
| # racing us and killing us first; we'll just try over and over |
| # until we win the race, and kill with pid -1 is atomic with |
| # respect to process creation. |
| while ! sudo -u chronos kill -9 -- -1 ; do |
| sleep .1 |
| done |
| |
| # Check for still-living chronos processes and log their status. |
| ps -u chronos --no-headers -o pid,stat,args | |
| logger -i -t "${JOB}-unkillable" -p crit |
| |
| bootstat other-processes-terminated |
| |
| # Android containers use run_oci to terminate and clean up containers. If |
| # run_oci exists, let run_oci perform the task first before falling back to |
| # general cleanup. Note that the cleanup is done here only when session_manager |
| # (e.g. crashes and) fails to kill/destroy the containers. |
| for container in /run/containers/*-run_oci ; do |
| # The '-run_oci' suffix above ensures that the run_oci commands below are |
| # executed only for containers started by run_oci. When run_oci is not |
| # installed in the rootfs, for example, these commands are never executed. |
| if [ -d "${container}" ]; then |
| run_oci --signal=KILL kill "${container##*/}" |
| NUM_RETRIES=3 |
| for i in $(seq ${NUM_RETRIES}) ; do |
| # Both sleep and polling are needed here because 'run_oci destroy' fails |
| # if the container process is still alive. |
| sleep 1 |
| run_oci destroy "${container##*/}" && break |
| if [ ${i} = ${NUM_RETRIES} ]; then |
| logger -i -p crit "Failed to destroy ${container##*/}" |
| fi |
| done |
| fi |
| done |
| |
| # If there are any orphaned containers, they should also be cleaned up. |
| # This needs to be done prior to cryptohome unmounting so that there are no |
| # remaining processes with files open that would prevent a clean unmount. |
| for container in /run/containers/* ; do |
| if [ -d "${container}" ]; then |
| kill_with_open_files_on "${container##*/}" "${container}/root" |
| umount -R "${container}/root" |
| rm -rf "${container}" |
| fi |
| done |
| |
| cryptohome --action=unmount |
| bootstat cryptohome-unmounted |