1#!/system/bin/sh
2
3# Copyright (C) 2014 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# Run tasks periodically.
18# Usage: $0 <delay_seconds> <timeout_seconds> <task_name> <task_binary>
19#
20# Executes task <task_name> by running <task_binary> every <delay_seconds>.
21
22set -e -u
23
24SCRIPT_NAME="$(basename "$0")"
25CHECK_DELAY=300  # Check every 5 minutes.
26KILL_DELAY=10    # How long to let the job clean up after a timeout.
27# Let the unittests override.
28: ${SPOOL_DIR:=/data/misc/crash_reporter/spool/cron-lite}
29
30loginfo() {
31  log -p i -t "${SCRIPT_NAME}" "$@"
32}
33
34trap "loginfo 'exiting'" EXIT
35
36check_and_fix_spool_paths() {
37  # Avoid weird spool paths if possible.
38  rm -f "$(dirname "${SPOOL_DIR}")" "${SPOOL_DIR}" 2>/dev/null || :
39  mkdir -p "${SPOOL_DIR}"
40  if [ ! -O "${SPOOL_DIR}" -o ! -d "${SPOOL_DIR}" ]; then
41    loginfo "Spool directory is damaged. Aborting!"
42    exit 1
43  fi
44}
45
46main() {
47  local delay="$1"
48  local timeout="$2"
49  local name="$3"
50  local spool_file="${SPOOL_DIR}/${name}"
51  shift 3
52
53  [ -z "${delay}" ] && exit 1
54  [ -z "${timeout}" ] && exit 1
55  [ -z "${name}" ] && exit 1
56  [ $# -eq 0 ] && exit 1
57  check_and_fix_spool_paths
58
59  while true; do
60    # Allow the sleep to be killed manually without terminating the handler.
61    # Send stderr to /dev/null to suppress the shell's "Terminated" message.
62    sleep $(( CHECK_DELAY + KILL_DELAY )) 2>/dev/null || true
63
64    [ ! -e "${spool_file}" ] && touch "${spool_file}"
65
66    local last_rotation="$(stat -c "%Y" "${spool_file}" 2>/dev/null || echo 0)"
67    local now="$(date +%s)"
68    local time_diff=$((now - last_rotation))
69
70    if [ ${time_diff} -gt ${delay} ]; then
71      rm "${spool_file}" || true
72      touch "${spool_file}"
73      loginfo "${name}: running $*"
74      timeout -k ${KILL_DELAY} ${timeout} "$@" || true
75      loginfo "${name}: job completed"
76    fi
77  done
78}
79
80main "$@"
81