OLD | NEW |
(Empty) | |
| 1 #!/bin/sh |
| 2 |
| 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. |
| 6 |
| 7 set -e |
| 8 |
| 9 # Product ID in crash report |
| 10 CHROMEOS_PRODUCT=ChromeOS |
| 11 |
| 12 # Send up to 8 crashes per day. |
| 13 MAX_CRASH_RATE=8 |
| 14 |
| 15 # Minidump uploading tool (provided by Google Breakpad). |
| 16 MINIDUMP_UPLOADER=/usr/bin/minidump_upload |
| 17 |
| 18 # URL to send non-official build crashes to. |
| 19 MINIDUMP_UPLOAD_STAGING_URL="http://clients2.google.com/cr/staging_report" |
| 20 |
| 21 # URL to send official build crashes to. |
| 22 MINIDUMP_UPLOAD_PROD_URL="http://clients2.google.com/cr/report" |
| 23 |
| 24 # File whose existence mocks crash sending. If empty we pretend the |
| 25 # crash sending was successful, otherwise unsuccessful. |
| 26 MOCK_CRASH_SENDING="/tmp/mock-crash-sending" |
| 27 |
| 28 # File whose existence causes crash sending to be delayed (for testing). |
| 29 PAUSE_CRASH_SENDING="/tmp/pause-crash-sending" |
| 30 |
| 31 # File whose existence implies we're running and not to start again. |
| 32 RUN_FILE="/var/run/crash_sender.pid" |
| 33 |
| 34 # Maximum time to sleep between sends. |
| 35 SECONDS_SEND_SPREAD=3600 |
| 36 |
| 37 # The syslog tag for all logging we emit. |
| 38 TAG="$(basename $0)[$$]" |
| 39 |
| 40 # Directory to store timestamp files indicating the uploads in the past 24 |
| 41 # hours. |
| 42 TIMESTAMPS_DIR="/var/lib/crash_sender" |
| 43 |
| 44 lecho() { |
| 45 logger -t "${TAG}" "$@" |
| 46 } |
| 47 |
| 48 remove_run_file() { |
| 49 rm -f "${RUN_FILE}" |
| 50 } |
| 51 |
| 52 check_not_already_running() { |
| 53 if [ ! -f "${RUN_FILE}" ]; then |
| 54 return |
| 55 fi |
| 56 local last_pid=$(cat "${RUN_FILE}") |
| 57 if [ ! -f "/proc/${last_pid}/cmdline" ]; then |
| 58 trap remove_run_file EXIT |
| 59 echo $$ > "${RUN_FILE}" |
| 60 return |
| 61 fi |
| 62 # This could just be an unrelated process, but it's ok to be conservative. |
| 63 lecho "Already running. Exiting now." |
| 64 exit 1 |
| 65 } |
| 66 |
| 67 get_version() { |
| 68 grep ^CHROMEOS_RELEASE_VERSION /etc/lsb-release | cut -d = -f 2- |
| 69 } |
| 70 |
| 71 # Generate a uniform random number in 0..max-1. |
| 72 generate_uniform_random() { |
| 73 local max=$1 |
| 74 local random="$(od -An -N4 -tu /dev/urandom)" |
| 75 echo $((random % max)) |
| 76 } |
| 77 |
| 78 is_feedback_disabled() { |
| 79 # See crosbug.com/3303. |
| 80 return 1 |
| 81 } |
| 82 |
| 83 is_on_3g() { |
| 84 # See crosbug.com/3304. |
| 85 return 1 |
| 86 } |
| 87 |
| 88 # Check if sending a crash now does not exceed the maximum 24hr rate and |
| 89 # commit to doing so, if not. |
| 90 check_rate() { |
| 91 mkdir -p ${TIMESTAMPS_DIR} |
| 92 # Only consider minidumps written in the past 24 hours by removing all older. |
| 93 find "${TIMESTAMPS_DIR}" -mindepth 1 -mmin +$((24 * 60)) -exec rm '{}' ';' |
| 94 local sends_in_24hrs=$(echo "${TIMESTAMPS_DIR}"/* | wc -w) |
| 95 lecho "Current send rate: ${sends_in_24hrs}sends/24hrs" |
| 96 if [ ${sends_in_24hrs} -ge ${MAX_CRASH_RATE} ]; then |
| 97 lecho "Cannot send more crashes:" |
| 98 lecho " current ${sends_in_24hrs}send/24hrs >= " \ |
| 99 "max ${MAX_CRASH_RATE}send/24hrs" |
| 100 return 1 |
| 101 fi |
| 102 mktemp "${TIMESTAMPS_DIR}"/XXXX > /dev/null |
| 103 return 0 |
| 104 } |
| 105 |
| 106 send_crash() { |
| 107 local sleep_time=$(generate_uniform_random $SECONDS_SEND_SPREAD) |
| 108 local url="${MINIDUMP_UPLOAD_STAGING_URL}" |
| 109 lecho "Sending crash:" |
| 110 lecho " Scheduled to send in ${sleep_time}s" |
| 111 lecho " Minidump: ${minidump_path}" |
| 112 lecho " URL: ${url}" |
| 113 lecho " Product: ${CHROMEOS_PRODUCT}" |
| 114 lecho " Version: ${chromeos_version}" |
| 115 if [ -s "${minidump_path}" ]; then |
| 116 # We cannot tell much from the minidump without symbols, but we can tell |
| 117 # at least what modules were loaded at the time of crash |
| 118 local modules="$(/usr/bin/minidump_dump "${minidump_path}" 2>&- | \ |
| 119 grep 'code_file' | sed -e 's/^.* = "//g;s/"//g' | \ |
| 120 tr '\n' ' ')" |
| 121 lecho " Mapped: ${modules}" |
| 122 fi |
| 123 if [ -f "${MOCK_CRASH_SENDING}" ]; then |
| 124 local mock_in=$(cat "${MOCK_CRASH_SENDING}") |
| 125 if [ "${mock_in}" = "" ]; then |
| 126 lecho "Mocking successful send" |
| 127 return 0 |
| 128 else |
| 129 lecho "Mocking unsuccessful send" |
| 130 return 1 |
| 131 fi |
| 132 fi |
| 133 |
| 134 if ! sleep ${sleep_time}; then |
| 135 lecho "Sleep failed" |
| 136 return 1 |
| 137 fi |
| 138 |
| 139 "${MINIDUMP_UPLOADER}" -p "${CHROMEOS_PRODUCT}" \ |
| 140 -v "${chromeos_version}" "${minidump_path}" "${url}" |
| 141 return $? |
| 142 } |
| 143 |
| 144 # Send all crashes from the given directory. The directory is currently |
| 145 # expected to just contain a bunch of minidumps - but this will change |
| 146 # over time to be a directory of directories where the minidump and core |
| 147 # file are in the directory as well as other metadata about the context |
| 148 # of the crash (executable name for instance). |
| 149 send_crashes() { |
| 150 local dir="$1" |
| 151 lecho "Considering crashes in ${dir}" |
| 152 # Cycle through minidumps, most recent first. That way if we're about |
| 153 # to exceed the daily rate, we send the most recent minidumps. |
| 154 if [ ! -d "${dir}" ]; then |
| 155 return |
| 156 fi |
| 157 for file in $(ls -1t "${dir}"); do |
| 158 local minidump_path="${dir}/${file}" |
| 159 lecho "Considering crash ${minidump_path}" |
| 160 if ! check_rate; then |
| 161 lecho "Sending ${minidump_path} would exceed rate. Leaving for later." |
| 162 return 0 |
| 163 fi |
| 164 local chromeos_version=$(get_version) |
| 165 if is_feedback_disabled; then |
| 166 lecho "Uploading is disabled. Removing crash." |
| 167 rm "${minidump_path}" |
| 168 elif is_on_3g; then |
| 169 lecho "Not sending crash report while on 3G, saving for later." |
| 170 elif send_crash ${minidump_path}; then |
| 171 # Send was successful, now remove |
| 172 lecho "Successfully sent crash ${minidump_path} and removing" |
| 173 rm "${minidump_path}" |
| 174 else |
| 175 lecho "Problem sending ${minidump_path}, not removing" |
| 176 fi |
| 177 done |
| 178 } |
| 179 |
| 180 main() { |
| 181 lecho "Starting" |
| 182 if [ -e "${PAUSE_CRASH_SENDING}" ]; then |
| 183 lecho "Exiting early due to ${PAUSE_CRASH_SENDING}" |
| 184 exit 1 |
| 185 fi |
| 186 |
| 187 check_not_already_running |
| 188 |
| 189 # Send system-wide crashes |
| 190 send_crashes "/var/spool/crash" |
| 191 |
| 192 # Send user-specific crashes |
| 193 send_crashes "/home/chronos/user/crash" |
| 194 |
| 195 lecho "Done" |
| 196 } |
| 197 |
| 198 main |
OLD | NEW |