| #!/system/bin/sh |
| |
| # Copyright (C) 2014 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| # Run tasks periodically. |
| # Usage: $0 <delay_seconds> <timeout_seconds> <task_name> <task_binary> |
| # |
| # Executes task <task_name> by running <task_binary> every <delay_seconds>. |
| |
| set -e -u |
| |
| get_key_value() { |
| local key="$1" value |
| |
| value=`getprop persist.nl.periodic_sched.${key}` |
| |
| echo "${value:-${2}}" |
| } |
| |
| SCRIPT_NAME="$(basename "$0")" |
| CHECK_DELAY=$(get_key_value "check" 300) # Check every X seconds. |
| KILL_DELAY=$(get_key_value "kill" 10) # How long to let the job clean up after a timeout. |
| |
| loginfo() { |
| log -p i -t "${SCRIPT_NAME}" "$@" |
| } |
| |
| trap "loginfo 'exiting'" EXIT |
| |
| check_and_fix_spool_paths() { |
| # Avoid weird spool paths if possible. |
| rm -f "$(dirname "$1")" "$1" 2>/dev/null || : |
| mkdir -p "$1" |
| if [ ! -O "$1" -o ! -d "$1" ]; then |
| loginfo "Spool directory is damaged. Aborting!" |
| exit 1 |
| fi |
| } |
| |
| main() { |
| local delay="$1" |
| local timeout="$2" |
| local name="$3" |
| local spool_dir="$4" |
| local spool_file="${spool_dir}/${name}" |
| shift 4 |
| |
| loginfo "Starting ${name}: d/t ${delay}/${timeout}" |
| |
| [ -z "${delay}" ] && exit 1 |
| [ -z "${timeout}" ] && exit 1 |
| [ -z "${name}" ] && exit 1 |
| [ -z "${spool_dir}" ] && exit 1 |
| [ $# -eq 0 ] && exit 1 |
| check_and_fix_spool_paths ${spool_dir} |
| |
| loginfo "Starting loop to run ${name}" |
| |
| while true; do |
| # Allow the sleep to be killed manually without terminating the handler. |
| # Send stderr to /dev/null to suppress the shell's "Terminated" message. |
| sleep $(( CHECK_DELAY + KILL_DELAY )) 2>/dev/null || true |
| |
| [ ! -e "${spool_file}" ] && touch "${spool_file}" |
| |
| local last_rotation="$(stat -c "%Y" "${spool_file}" 2>/dev/null || echo 0)" |
| local now="$(date +%s)" |
| local time_diff=$((now - last_rotation)) |
| |
| loginfo "Time diff after sleep: ${time_diff}" |
| if [ ${time_diff} -lt 0 ]; then |
| # The spool file has a future timestamp. Fix by deleting the spool file |
| # and re-creating. |
| loginfo "${name}: corrupted spool file? Re-creating ${spool_file}" |
| rm "${spool_file}" || true |
| touch "${spool_file}" |
| fi |
| |
| if [ ${time_diff} -gt ${delay} ]; then |
| rm "${spool_file}" || true |
| touch "${spool_file}" |
| loginfo "${name}: running $*" |
| timeout -k ${KILL_DELAY} ${timeout} "$@" || true |
| loginfo "${name}: job completed" |
| fi |
| done |
| } |
| |
| main "$@" |