| OLD | NEW |
| 1 #!/bin/sh | 1 #!/bin/sh |
| 2 | 2 |
| 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 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 | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 set -e | 7 set -e |
| 8 | 8 |
| 9 # Product ID in crash report | 9 # Product ID in crash report |
| 10 CHROMEOS_PRODUCT=ChromeOS | 10 CHROMEOS_PRODUCT=ChromeOS |
| 11 | 11 |
| 12 # File whose existence implies crash reports may be sent, and whose | 12 # File whose existence implies crash reports may be sent, and whose |
| 13 # contents includes our machine's anonymized guid. | 13 # contents includes our machine's anonymized guid. |
| 14 CONSENT_ID="/home/chronos/Consent To Send Stats" | 14 CONSENT_ID="/home/chronos/Consent To Send Stats" |
| 15 | 15 |
| 16 # Send up to 8 crashes per day. | 16 # Send up to 8 crashes per day. |
| 17 MAX_CRASH_RATE=8 | 17 MAX_CRASH_RATE=8 |
| 18 | 18 |
| 19 # URL to send non-official build crashes to. | |
| 20 MINIDUMP_UPLOAD_STAGING_URL="http://clients2.google.com/cr/staging_report" | |
| 21 | |
| 22 # URL to send official build crashes to. | |
| 23 MINIDUMP_UPLOAD_PROD_URL="http://clients2.google.com/cr/report" | |
| 24 | |
| 25 # File whose existence mocks crash sending. If empty we pretend the | 19 # File whose existence mocks crash sending. If empty we pretend the |
| 26 # crash sending was successful, otherwise unsuccessful. | 20 # crash sending was successful, otherwise unsuccessful. |
| 27 MOCK_CRASH_SENDING="/tmp/mock-crash-sending" | 21 MOCK_CRASH_SENDING="/tmp/mock-crash-sending" |
| 28 | 22 |
| 29 # File whose existence causes crash sending to be delayed (for testing). | 23 # File whose existence causes crash sending to be delayed (for testing). |
| 30 PAUSE_CRASH_SENDING="/tmp/pause-crash-sending" | 24 # Must be stateful to enable testing kernel crashes. |
| 25 PAUSE_CRASH_SENDING="/var/lib/crash_sender_paused" |
| 26 |
| 27 # URL to send non-official build crash reports to. |
| 28 REPORT_UPLOAD_STAGING_URL="http://clients2.google.com/cr/staging_report" |
| 29 |
| 30 # URL to send official build crash reports to. |
| 31 REPORT_UPLOAD_PROD_URL="http://clients2.google.com/cr/report" |
| 31 | 32 |
| 32 # File whose existence implies we're running and not to start again. | 33 # File whose existence implies we're running and not to start again. |
| 33 RUN_FILE="/var/run/crash_sender.pid" | 34 RUN_FILE="/var/run/crash_sender.pid" |
| 34 | 35 |
| 35 # Maximum time to sleep between sends. | 36 # Maximum time to sleep between sends. |
| 36 SECONDS_SEND_SPREAD=${SECONDS_SEND_SPREAD:-600} | 37 SECONDS_SEND_SPREAD=${SECONDS_SEND_SPREAD:-600} |
| 37 | 38 |
| 38 # The syslog tag for all logging we emit. | 39 # The syslog tag for all logging we emit. |
| 39 TAG="$(basename $0)[$$]" | 40 TAG="$(basename $0)[$$]" |
| 40 | 41 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 | 94 |
| 94 is_on_3g() { | 95 is_on_3g() { |
| 95 # See crosbug.com/3304. | 96 # See crosbug.com/3304. |
| 96 return 1 | 97 return 1 |
| 97 } | 98 } |
| 98 | 99 |
| 99 # Check if sending a crash now does not exceed the maximum 24hr rate and | 100 # Check if sending a crash now does not exceed the maximum 24hr rate and |
| 100 # commit to doing so, if not. | 101 # commit to doing so, if not. |
| 101 check_rate() { | 102 check_rate() { |
| 102 mkdir -p ${TIMESTAMPS_DIR} | 103 mkdir -p ${TIMESTAMPS_DIR} |
| 103 # Only consider minidumps written in the past 24 hours by removing all older. | 104 # Only consider reports written in the past 24 hours by removing all older. |
| 104 find "${TIMESTAMPS_DIR}" -mindepth 1 -mmin +$((24 * 60)) -exec rm '{}' ';' | 105 find "${TIMESTAMPS_DIR}" -mindepth 1 -mmin +$((24 * 60)) -exec rm '{}' ';' |
| 105 local sends_in_24hrs=$(echo "${TIMESTAMPS_DIR}"/* | wc -w) | 106 local sends_in_24hrs=$(echo "${TIMESTAMPS_DIR}"/* | wc -w) |
| 106 lecho "Current send rate: ${sends_in_24hrs}sends/24hrs" | 107 lecho "Current send rate: ${sends_in_24hrs}sends/24hrs" |
| 107 if [ ${sends_in_24hrs} -ge ${MAX_CRASH_RATE} ]; then | 108 if [ ${sends_in_24hrs} -ge ${MAX_CRASH_RATE} ]; then |
| 108 lecho "Cannot send more crashes:" | 109 lecho "Cannot send more crashes:" |
| 109 lecho " current ${sends_in_24hrs}send/24hrs >= " \ | 110 lecho " current ${sends_in_24hrs}send/24hrs >= " \ |
| 110 "max ${MAX_CRASH_RATE}send/24hrs" | 111 "max ${MAX_CRASH_RATE}send/24hrs" |
| 111 return 1 | 112 return 1 |
| 112 fi | 113 fi |
| 113 mktemp "${TIMESTAMPS_DIR}"/XXXX > /dev/null | 114 mktemp "${TIMESTAMPS_DIR}"/XXXX > /dev/null |
| 114 return 0 | 115 return 0 |
| 115 } | 116 } |
| 116 | 117 |
| 117 # Return if $1 is a .core file | 118 # Return if $1 is a .core file |
| 118 is_core_file() { | 119 get_kind() { |
| 119 local filename=$1 | 120 local kind="${1##*.}" |
| 120 [ "${filename##*.}" = "core" ] | 121 if [ "${kind}" = "dmp" ]; then |
| 122 kind="minidump" |
| 123 fi |
| 124 echo ${kind} |
| 125 } |
| 126 |
| 127 get_exec_name() { |
| 128 local filename=$(basename "$1") |
| 129 echo "${filename%%.*}" |
| 121 } | 130 } |
| 122 | 131 |
| 123 send_crash() { | 132 send_crash() { |
| 133 local report_path="$1" |
| 134 local kind=$(get_kind "${report_path}") |
| 135 local exec_name=$(get_exec_name "${report_path}") |
| 124 local sleep_time=$(generate_uniform_random $SECONDS_SEND_SPREAD) | 136 local sleep_time=$(generate_uniform_random $SECONDS_SEND_SPREAD) |
| 125 local url="${MINIDUMP_UPLOAD_STAGING_URL}" | 137 local url="${REPORT_UPLOAD_STAGING_URL}" |
| 126 if is_official; then | 138 if is_official; then |
| 127 url="${MINIDUMP_UPLOAD_PROD_URL}" | 139 url="${REPORT_UPLOAD_PROD_URL}" |
| 128 fi | 140 fi |
| 129 lecho "Sending crash:" | 141 lecho "Sending crash:" |
| 130 lecho " Scheduled to send in ${sleep_time}s" | 142 lecho " Scheduled to send in ${sleep_time}s" |
| 131 lecho " Minidump: ${minidump_path}" | 143 lecho " Report: ${report_path} (${kind})" |
| 132 lecho " URL: ${url}" | 144 lecho " URL: ${url}" |
| 133 lecho " Product: ${CHROMEOS_PRODUCT}" | 145 lecho " Product: ${CHROMEOS_PRODUCT}" |
| 134 lecho " Version: ${chromeos_version}" | 146 lecho " Version: ${chromeos_version}" |
| 135 if [ -s "${minidump_path}" ]; then | 147 lecho " Exec name: ${exec_name}" |
| 136 # We cannot tell much from the minidump without symbols, but we can tell | |
| 137 # at least what modules were loaded at the time of crash | |
| 138 local modules="$(/usr/bin/minidump_dump "${minidump_path}" 2>&- | \ | |
| 139 grep 'code_file' | sed -e 's/^.* = "//g;s/"//g' | \ | |
| 140 tr '\n' ' ')" | |
| 141 lecho " Mapped: ${modules}" | |
| 142 fi | |
| 143 if [ -f "${MOCK_CRASH_SENDING}" ]; then | 148 if [ -f "${MOCK_CRASH_SENDING}" ]; then |
| 144 local mock_in=$(cat "${MOCK_CRASH_SENDING}") | 149 local mock_in=$(cat "${MOCK_CRASH_SENDING}") |
| 145 if [ "${mock_in}" = "" ]; then | 150 if [ "${mock_in}" = "" ]; then |
| 146 lecho "Mocking successful send" | 151 lecho "Mocking successful send" |
| 147 return 0 | 152 return 0 |
| 148 else | 153 else |
| 149 lecho "Mocking unsuccessful send" | 154 lecho "Mocking unsuccessful send" |
| 150 return 1 | 155 return 1 |
| 151 fi | 156 fi |
| 152 fi | 157 fi |
| 153 | 158 |
| 154 if ! sleep ${sleep_time}; then | 159 if ! sleep ${sleep_time}; then |
| 155 lecho "Sleep failed" | 160 lecho "Sleep failed" |
| 156 return 1 | 161 return 1 |
| 157 fi | 162 fi |
| 158 | 163 |
| 159 local report_id="${TMP_DIR}/report_id" | 164 local report_id="${TMP_DIR}/report_id" |
| 160 local curl_stderr="${TMP_DIR}/curl_stderr" | 165 local curl_stderr="${TMP_DIR}/curl_stderr" |
| 161 | 166 |
| 162 set +e | 167 set +e |
| 163 curl "${url}" \ | 168 curl "${url}" \ |
| 164 -F "prod=${CHROMEOS_PRODUCT}" \ | 169 -F "prod=${CHROMEOS_PRODUCT}" \ |
| 165 -F "ver=${chromeos_version}" \ | 170 -F "ver=${chromeos_version}" \ |
| 166 -F "upload_file_minidump=@${minidump_path}" \ | 171 -F "upload_file_${kind}=@${report_path}" \ |
| 172 -F "exec_name=${exec_name}" \ |
| 167 -F "guid=<${CONSENT_ID}" -o "${report_id}" 2>"${curl_stderr}" | 173 -F "guid=<${CONSENT_ID}" -o "${report_id}" 2>"${curl_stderr}" |
| 168 local curl_result=$? | 174 curl_result=$? |
| 169 set -e | 175 set -e |
| 170 | 176 |
| 171 if [ ${curl_result} -eq 0 ]; then | 177 if [ ${curl_result} -eq 0 ]; then |
| 172 lecho "Crash report receipt ID $(cat ${report_id})" | 178 lecho "Crash report receipt ID $(cat ${report_id})" |
| 173 else | 179 else |
| 174 lecho "Crash sending failed with: $(cat ${curl_stderr})" | 180 lecho "Crash sending failed with: $(cat ${curl_stderr})" |
| 175 fi | 181 fi |
| 176 | 182 |
| 177 rm -f "${report_id}" "${output_file}" | 183 rm -f "${report_id}" "${output_file}" |
| 178 | 184 |
| 179 return ${curl_result} | 185 return ${curl_result} |
| 180 } | 186 } |
| 181 | 187 |
| 182 # Send all crashes from the given directory. The directory is currently | 188 # Send all crashes from the given directory. The directory is currently |
| 183 # expected to just contain a bunch of minidumps. | 189 # expected to just contain a bunch of minidumps. |
| 184 send_crashes() { | 190 send_crashes() { |
| 185 local dir="$1" | 191 local dir="$1" |
| 186 lecho "Considering crashes in ${dir}" | 192 lecho "Considering crashes in ${dir}" |
| 187 | 193 |
| 188 # Cycle through minidumps, most recent first. That way if we're about | 194 # Cycle through minidumps, most recent first. That way if we're about |
| 189 # to exceed the daily rate, we send the most recent minidumps. | 195 # to exceed the daily rate, we send the most recent minidumps. |
| 190 if [ ! -d "${dir}" ]; then | 196 if [ ! -d "${dir}" ]; then |
| 191 return | 197 return |
| 192 fi | 198 fi |
| 193 for file in $(ls -1t "${dir}"); do | 199 for file in $(ls -1t "${dir}"); do |
| 194 local minidump_path="${dir}/${file}" | 200 local report_path="${dir}/${file}" |
| 195 lecho "Considering file ${minidump_path}" | 201 lecho "Considering file ${report_path}" |
| 196 if is_core_file "${minidump_path}"; then | 202 local kind=$(get_kind "${report_path}") |
| 203 |
| 204 if [ "${kind}" = "core" ]; then |
| 197 lecho "Ignoring core file." | 205 lecho "Ignoring core file." |
| 198 continue | 206 continue |
| 207 elif [ "${kind}" != "minidump" ] && [ "${kind}" != "kcrash" ]; then |
| 208 lecho "Unknown report kind: ${kind}. Removing report." |
| 209 rm -f "${report_path}" |
| 210 continue |
| 199 fi | 211 fi |
| 200 if ! check_rate; then | 212 if ! check_rate; then |
| 201 lecho "Sending ${minidump_path} would exceed rate. Leaving for later." | 213 lecho "Sending ${report_path} would exceed rate. Leaving for later." |
| 202 return 0 | 214 return 0 |
| 203 fi | 215 fi |
| 204 local chromeos_version=$(get_version) | 216 local chromeos_version=$(get_version) |
| 205 if is_feedback_disabled; then | 217 if is_feedback_disabled; then |
| 206 lecho "Uploading is disabled. Removing crash." | 218 lecho "Uploading is disabled. Removing crash." |
| 207 rm "${minidump_path}" | 219 rm "${report_path}" |
| 208 elif is_on_3g; then | 220 elif is_on_3g; then |
| 209 lecho "Not sending crash report while on 3G, saving for later." | 221 lecho "Not sending crash report while on 3G, saving for later." |
| 210 elif send_crash ${minidump_path}; then | 222 elif send_crash "${report_path}"; then |
| 211 # Send was successful, now remove | 223 # Send was successful, now remove |
| 212 lecho "Successfully sent crash ${minidump_path} and removing" | 224 lecho "Successfully sent crash ${report_path} and removing" |
| 213 rm "${minidump_path}" | 225 rm "${report_path}" |
| 214 else | 226 else |
| 215 lecho "Problem sending ${minidump_path}, not removing" | 227 lecho "Problem sending ${report_path}, not removing" |
| 216 fi | 228 fi |
| 217 done | 229 done |
| 218 } | 230 } |
| 219 | 231 |
| 220 main() { | 232 main() { |
| 221 if [ -e "${PAUSE_CRASH_SENDING}" ]; then | 233 if [ -e "${PAUSE_CRASH_SENDING}" ]; then |
| 222 lecho "Exiting early due to ${PAUSE_CRASH_SENDING}" | 234 lecho "Exiting early due to ${PAUSE_CRASH_SENDING}" |
| 223 exit 1 | 235 exit 1 |
| 224 fi | 236 fi |
| 225 | 237 |
| 226 check_not_already_running | 238 check_not_already_running |
| 227 | 239 |
| 228 TMP_DIR="$(mktemp -d /tmp/crash_sender.XXXX)" | 240 TMP_DIR="$(mktemp -d /tmp/crash_sender.XXXX)" |
| 229 trap cleanup_tmp_dir EXIT INT | 241 trap cleanup_tmp_dir EXIT INT |
| 230 | 242 |
| 231 # Send system-wide crashes | 243 # Send system-wide crashes |
| 232 send_crashes "/var/spool/crash" | 244 send_crashes "/var/spool/crash" |
| 233 | 245 |
| 234 # Send user-specific crashes | 246 # Send user-specific crashes |
| 235 send_crashes "/home/chronos/user/crash" | 247 send_crashes "/home/chronos/user/crash" |
| 236 } | 248 } |
| 237 | 249 |
| 238 main | 250 main |
| OLD | NEW |