Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: crash_sender

Issue 3436029: crash-reporter: Send OS version at time of crash and related improvements (Closed) Base URL: http://git.chromium.org/git/crash-reporter.git
Patch Set: respond to petkov review Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « crash_reporter.cc ('k') | kernel_collector.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 # Should remove the run file when this process finishes. We don't want 12 # Should remove the run file when this process finishes. We don't want
13 # to always remove it since it may be for pre-existing crash_sender 13 # to always remove it since it may be for pre-existing crash_sender
14 # process. 14 # process.
15 CLEAN_UP_RUN_FILE=0 15 CLEAN_UP_RUN_FILE=0
16 16
17 # File whose existence implies crash reports may be sent, and whose 17 # File whose existence implies crash reports may be sent, and whose
18 # contents includes our machine's anonymized guid. 18 # contents includes our machine's anonymized guid.
19 CONSENT_ID="/home/chronos/Consent To Send Stats" 19 CONSENT_ID="/home/chronos/Consent To Send Stats"
20 20
21 # Path to find which is required for computing the crash rate. 21 # Path to find which is required for computing the crash rate.
22 FIND="/usr/bin/find" 22 FIND="/usr/bin/find"
23 23
24 # Set this to 1 in the environment to allow uploading crash reports
25 # for unofficial versions.
26 FORCE_OFFICIAL=${FORCE_OFFICIAL:-0}
27
28 # Path to hardware class description.
29 HWCLASS_PATH="/sys/devices/platform/chromeos_acpi/HWID"
30
24 # Maximum crashes to send per day. 31 # Maximum crashes to send per day.
25 MAX_CRASH_RATE=32 32 MAX_CRASH_RATE=${MAX_CRASH_RATE:-32}
26 33
27 # File whose existence mocks crash sending. If empty we pretend the 34 # File whose existence mocks crash sending. If empty we pretend the
28 # crash sending was successful, otherwise unsuccessful. 35 # crash sending was successful, otherwise unsuccessful.
29 MOCK_CRASH_SENDING="/tmp/mock-crash-sending" 36 MOCK_CRASH_SENDING="/tmp/mock-crash-sending"
30 37
31 # File whose existence causes crash sending to be delayed (for testing). 38 # File whose existence causes crash sending to be delayed (for testing).
32 # Must be stateful to enable testing kernel crashes. 39 # Must be stateful to enable testing kernel crashes.
33 PAUSE_CRASH_SENDING="/var/lib/crash_sender_paused" 40 PAUSE_CRASH_SENDING="/var/lib/crash_sender_paused"
34 41
35 # URL to send non-official build crash reports to.
36 REPORT_UPLOAD_STAGING_URL="http://clients2.google.com/cr/staging_report"
37
38 # URL to send official build crash reports to. 42 # URL to send official build crash reports to.
39 REPORT_UPLOAD_PROD_URL="http://clients2.google.com/cr/report" 43 REPORT_UPLOAD_PROD_URL="http://clients2.google.com/cr/report"
40 44
41 # File whose existence implies we're running and not to start again. 45 # File whose existence implies we're running and not to start again.
42 RUN_FILE="/var/run/crash_sender.pid" 46 RUN_FILE="/var/run/crash_sender.pid"
43 47
44 # Maximum time to sleep between sends. 48 # Maximum time to sleep between sends.
45 SECONDS_SEND_SPREAD=${SECONDS_SEND_SPREAD:-600} 49 SECONDS_SEND_SPREAD=${SECONDS_SEND_SPREAD:-600}
46 50
47 # The syslog tag for all logging we emit. 51 # The syslog tag for all logging we emit.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 # Note that this write may be executed by two crash_senders who 86 # Note that this write may be executed by two crash_senders who
83 # simulataneously reap the existing dangling run file 87 # simulataneously reap the existing dangling run file
84 echo $$ > "${RUN_FILE}" 88 echo $$ > "${RUN_FILE}"
85 return 89 return
86 fi 90 fi
87 # This could just be an unrelated process, but it's ok to be conservative. 91 # This could just be an unrelated process, but it's ok to be conservative.
88 lecho "Already running. Exiting now." 92 lecho "Already running. Exiting now."
89 exit 1 93 exit 1
90 } 94 }
91 95
92 get_version() {
93 grep ^CHROMEOS_RELEASE_VERSION /etc/lsb-release | cut -d = -f 2-
94 }
95
96 is_official() { 96 is_official() {
97 [ ${FORCE_OFFICIAL} -ne 0 ] && return 0
97 grep ^CHROMEOS_RELEASE_DESCRIPTION /etc/lsb-release | grep -q Official 98 grep ^CHROMEOS_RELEASE_DESCRIPTION /etc/lsb-release | grep -q Official
98 } 99 }
99 100
100 # Generate a uniform random number in 0..max-1. 101 # Generate a uniform random number in 0..max-1.
101 generate_uniform_random() { 102 generate_uniform_random() {
102 local max=$1 103 local max=$1
103 local random="$(od -An -N4 -tu /dev/urandom)" 104 local random="$(od -An -N4 -tu /dev/urandom)"
104 echo $((random % max)) 105 echo $((random % max))
105 } 106 }
106 107
107 is_feedback_disabled() { 108 is_feedback_disabled() {
108 [ -r "${CONSENT_ID}" ] && return 1 109 [ -r "${CONSENT_ID}" ] && return 1
109 return 0 110 return 0
110 } 111 }
111 112
112 is_on_3g() { 113 is_on_3g() {
113 # See crosbug.com/3304. 114 # See crosbug.com/3304.
114 return 1 115 return 1
115 } 116 }
116 117
117 # Check if sending a crash now does not exceed the maximum 24hr rate and 118 # Check if sending a crash now does not exceed the maximum 24hr rate and
118 # commit to doing so, if not. 119 # commit to doing so, if not.
119 check_rate() { 120 check_rate() {
120 mkdir -p ${TIMESTAMPS_DIR} 121 mkdir -p ${TIMESTAMPS_DIR}
121 # Only consider minidumps written in the past 24 hours by removing all older. 122 # Only consider minidumps written in the past 24 hours by removing all older.
122 ${FIND} "${TIMESTAMPS_DIR}" -mindepth 1 -mmin +$((24 * 60)) -exec rm '{}' ';' 123 ${FIND} "${TIMESTAMPS_DIR}" -mindepth 1 -mmin +$((24 * 60)) \
124 -exec rm -- '{}' ';'
123 local sends_in_24hrs=$(echo "${TIMESTAMPS_DIR}"/* | wc -w) 125 local sends_in_24hrs=$(echo "${TIMESTAMPS_DIR}"/* | wc -w)
124 lecho "Current send rate: ${sends_in_24hrs}sends/24hrs" 126 lecho "Current send rate: ${sends_in_24hrs}sends/24hrs"
125 if [ ${sends_in_24hrs} -ge ${MAX_CRASH_RATE} ]; then 127 if [ ${sends_in_24hrs} -ge ${MAX_CRASH_RATE} ]; then
126 lecho "Cannot send more crashes:" 128 lecho "Cannot send more crashes:"
127 lecho " current ${sends_in_24hrs}send/24hrs >= " \ 129 lecho " current ${sends_in_24hrs}send/24hrs >= " \
128 "max ${MAX_CRASH_RATE}send/24hrs" 130 "max ${MAX_CRASH_RATE}send/24hrs"
129 return 1 131 return 1
130 fi 132 fi
131 mktemp "${TIMESTAMPS_DIR}"/XXXX > /dev/null 133 mktemp "${TIMESTAMPS_DIR}"/XXXX > /dev/null
132 return 0 134 return 0
133 } 135 }
134 136
135 # Return if $1 is a .core file 137 # Gets the base part of a crash report file, such as
136 get_kind() { 138 # name.01234.5678.9012 from name.01234.5678.9012.meta
137 local kind="${1##*.}" 139 get_base() {
138 if [ "${kind}" = "dmp" ]; then 140 echo "${1%.*}"
139 kind="minidump"
140 fi
141 echo ${kind}
142 } 141 }
143 142
144 get_exec_name() { 143 # Return which kind of report the given metadata file relates to
145 local filename=$(basename "$1") 144 get_kind() {
146 echo "${filename%%.*}" 145 # There should never be a report with both a dmp and kcrash file.
146 # If that were to happen we arbitrarily consider this a minidump
147 # report and effectively ignore the kcrash.
148 local base="$(get_base "$1")"
149 if [ -r "${base}.dmp" ]; then
150 echo "minidump"
151 return
152 fi
153 if [ -r "${base}.kcrash" ]; then
154 echo "kcrash"
155 return
156 fi
157 }
158
159 get_key_value() {
160 if ! grep -q "$2=" "$1"; then
161 echo "undefined"
162 return
163 fi
164 grep "$2=" "$1" | cut -d = -f 2-
165 }
166
167 # Returns true if mock is enabled.
168 is_mock() {
169 [ -f "${MOCK_CRASH_SENDING}" ] && return 0
170 return 1
171 }
172
173 # Return the board name.
174 get_board() {
175 echo $(get_key_value "/etc/lsb-release" "CHROMEOS_RELEASE_BOARD")
176 }
177
178 # Return the hardware class or "unknown".
179 get_hardware_class() {
180 if [ -r "${HWCLASS_PATH}" ]; then
181 cat "${HWCLASS_PATH}"
182 else
183 echo "unknown"
184 fi
147 } 185 }
148 186
149 send_crash() { 187 send_crash() {
150 local report_path="$1" 188 local meta_path="$1"
151 local kind=$(get_kind "${report_path}") 189 local kind="$(get_kind "${meta_path}")"
152 local exec_name=$(get_exec_name "${report_path}") 190 local exec_name="$(get_key_value "${meta_path}" "exec_name")"
153 local sleep_time=$(generate_uniform_random $SECONDS_SEND_SPREAD) 191 local sleep_time=$(generate_uniform_random $SECONDS_SEND_SPREAD)
154 local url="${REPORT_UPLOAD_STAGING_URL}" 192 local url="${REPORT_UPLOAD_PROD_URL}"
155 if is_official; then 193 local chromeos_version="$(get_key_value "${meta_path}" "ver")"
156 url="${REPORT_UPLOAD_PROD_URL}" 194 local board="$(get_board)"
157 fi 195 local hwclass="$(get_hardware_class)"
196 local payload_extension="${kind}"
197 [ "${kind}" = "minidump" ] && payload_extension="dmp"
198 local report_payload="$(get_base "${meta_path}").${payload_extension}"
158 lecho "Sending crash:" 199 lecho "Sending crash:"
159 lecho " Scheduled to send in ${sleep_time}s" 200 lecho " Scheduled to send in ${sleep_time}s"
160 lecho " Report: ${report_path} (${kind})" 201 lecho " Metadata: ${meta_path} (${kind})"
161 lecho " URL: ${url}" 202 lecho " Payload: ${report_payload}"
162 lecho " Product: ${CHROMEOS_PRODUCT}"
163 lecho " Version: ${chromeos_version}" 203 lecho " Version: ${chromeos_version}"
204 if is_mock; then
205 lecho " Product: ${CHROMEOS_PRODUCT}"
206 lecho " URL: ${url}"
207 lecho " Board: ${board}"
208 lecho " HWClass: ${hwclass}"
209 fi
164 lecho " Exec name: ${exec_name}" 210 lecho " Exec name: ${exec_name}"
165 if [ -f "${MOCK_CRASH_SENDING}" ]; then 211 if is_mock; then
166 local mock_in=$(cat "${MOCK_CRASH_SENDING}") 212 local mock_in=$(cat "${MOCK_CRASH_SENDING}")
167 if [ "${mock_in}" = "" ]; then 213 if [ "${mock_in}" = "" ]; then
168 lecho "Mocking successful send" 214 lecho "Mocking successful send"
169 return 0 215 return 0
170 else 216 else
171 lecho "Mocking unsuccessful send" 217 lecho "Mocking unsuccessful send"
172 return 1 218 return 1
173 fi 219 fi
174 fi 220 fi
175 221
176 if ! sleep ${sleep_time}; then 222 if ! sleep ${sleep_time}; then
177 lecho "Sleep failed" 223 lecho "Sleep failed"
178 return 1 224 return 1
179 fi 225 fi
180 226
181 local report_id="${TMP_DIR}/report_id" 227 local report_id="${TMP_DIR}/report_id"
182 local curl_stderr="${TMP_DIR}/curl_stderr" 228 local curl_stderr="${TMP_DIR}/curl_stderr"
183 229
184 set +e 230 set +e
185 curl "${url}" \ 231 curl "${url}" \
186 -F "prod=${CHROMEOS_PRODUCT}" \ 232 -F "prod=${CHROMEOS_PRODUCT}" \
187 -F "ver=${chromeos_version}" \ 233 -F "ver=${chromeos_version}" \
188 -F "upload_file_${kind}=@${report_path}" \ 234 -F "upload_file_${kind}=@${report_payload}" \
235 -F "board=${board}" \
236 -F "hwclass=${hwclass}" \
189 -F "exec_name=${exec_name}" \ 237 -F "exec_name=${exec_name}" \
190 -F "guid=<${CONSENT_ID}" -o "${report_id}" 2>"${curl_stderr}" 238 -F "guid=<${CONSENT_ID}" -o "${report_id}" 2>"${curl_stderr}"
191 curl_result=$? 239 curl_result=$?
192 set -e 240 set -e
193 241
194 if [ ${curl_result} -eq 0 ]; then 242 if [ ${curl_result} -eq 0 ]; then
195 lecho "Crash report receipt ID $(cat ${report_id})" 243 lecho "Crash report receipt ID $(cat ${report_id})"
196 else 244 else
197 lecho "Crash sending failed with: $(cat ${curl_stderr})" 245 lecho "Crash sending failed with: $(cat ${curl_stderr})"
198 fi 246 fi
199 247
200 rm -f "${report_id}" 248 rm -f "${report_id}"
201 249
202 return ${curl_result} 250 return ${curl_result}
203 } 251 }
204 252
253 # *.meta files always end with done=1 so we can tell if they are complete.
254 is_complete_metadata() {
255 grep -q "done=1" "$1"
256 }
257
258 # Remove the given report path.
259 remove_report() {
260 local base="${1%.*}"
261 rm -f -- "${base}".*
262 }
263
205 # Send all crashes from the given directory. 264 # Send all crashes from the given directory.
206 send_crashes() { 265 send_crashes() {
207 local dir="$1" 266 local dir="$1"
208 lecho "Considering crashes in ${dir}"
209 267
210 # Cycle through minidumps, most recent first. That way if we're about 268 # Cycle through minidumps, most recent first. That way if we're about
211 # to exceed the daily rate, we send the most recent minidumps. 269 # to exceed the daily rate, we send the most recent minidumps.
212 if [ ! -d "${dir}" ]; then 270 if [ ! -d "${dir}" ]; then
213 return 271 return
214 fi 272 fi
215 for file in $(ls -1t "${dir}"); do
216 local report_path="${dir}/${file}"
217 lecho "Considering file ${report_path}"
218 local kind=$(get_kind "${report_path}")
219 273
220 if [ "${kind}" = "core" ]; then 274 # Consider any old files which still have no corresponding meta file
221 lecho "Ignoring core file." 275 # as orphaned, and remove them.
222 continue 276 for old_file in $(${FIND} "${dir}" -mindepth 1 \
223 elif [ "${kind}" != "minidump" ] && [ "${kind}" != "kcrash" ]; then 277 -mmin +$((24 * 60)) -type f); do
224 lecho "Unknown report kind: ${kind}. Removing report." 278 if [ ! -e "$(get_base "${old_file}").meta" ]; then
225 rm -f "${report_path}" 279 lecho "Removing old orphaned file: ${old_file}."
280 rm -f -- "${old_file}"
281 fi
282 done
283
284 # Look through all metadata (*.meta) files, if any exist.
285 for meta_path in $(ls -1t "${dir}"/*.meta 2>/dev/null); do
286 lecho "Considering metadata ${meta_path}."
287 local kind=$(get_kind "${meta_path}")
288
289 if [ "${kind}" != "minidump" ] && [ "${kind}" != "kcrash" ]; then
290 lecho "Unknown report kind. Removing report."
291 remove_report "${meta_path}"
226 continue 292 continue
227 fi 293 fi
228 if ! check_rate; then 294
229 lecho "Sending ${report_path} would exceed rate. Leaving for later." 295 if is_feedback_disabled; then
296 lecho "Uploading is disabled. Removing crash."
297 remove_report "${meta_path}"
298 continue
299 fi
300
301 if ! is_mock && ! is_official; then
302 lecho "Not an official OS version. Removing crash."
303 remove_report "${meta_path}"
304 continue
305 fi
306
307 if is_on_3g; then
308 lecho "Not sending crash reports while on 3G, saving for later."
230 return 0 309 return 0
231 fi 310 fi
232 local chromeos_version=$(get_version) 311
233 if is_feedback_disabled; then 312 if ! is_complete_metadata "${meta_path}"; then
234 lecho "Uploading is disabled. Removing crash." 313 # This report is incomplete, so if it's old, just remove it.
235 rm "${report_path}" 314 local old_meta=$(${FIND} "${dir}" -mindepth 1 -name \
236 elif is_on_3g; then 315 $(basename "${meta_path}") -mmin +$((24 * 60)) -type f)
237 lecho "Not sending crash report while on 3G, saving for later." 316 if [ -n "${old_meta}" ]; then
238 elif send_crash "${report_path}"; then 317 lecho "Removing old incomplete metadata."
239 # Send was successful, now remove 318 remove_report "${meta_path}"
240 lecho "Successfully sent crash ${report_path} and removing" 319 else
241 rm "${report_path}" 320 lecho "Ignoring recent incomplete metadata."
242 else 321 fi
243 lecho "Problem sending ${report_path}, not removing" 322 continue
244 fi 323 fi
324
325 if ! check_rate; then
326 lecho "Sending ${meta_path} would exceed rate. Leaving for later."
327 return 0
328 fi
329
330 if ! send_crash "${meta_path}"; then
331 lecho "Problem sending ${meta_path}, not removing."
332 continue
333 fi
334
335 # Send was successful, now remove.
336 lecho "Successfully sent crash ${meta_path} and removing."
337 remove_report "${meta_path}"
245 done 338 done
246 } 339 }
247 340
248 main() { 341 main() {
249 trap cleanup EXIT INT TERM 342 trap cleanup EXIT INT TERM
250 if [ -e "${PAUSE_CRASH_SENDING}" ]; then 343 if [ -e "${PAUSE_CRASH_SENDING}" ]; then
251 lecho "Exiting early due to ${PAUSE_CRASH_SENDING}" 344 lecho "Exiting early due to ${PAUSE_CRASH_SENDING}."
252 exit 1 345 exit 1
253 fi 346 fi
254 347
255 check_not_already_running 348 check_not_already_running
256 349
257 if [ ! -x "${FIND}" ]; then 350 if [ ! -x "${FIND}" ]; then
258 lecho "Fatal: Crash sending disabled: ${FIND} not found." 351 lecho "Fatal: Crash sending disabled: ${FIND} not found."
259 exit 1 352 exit 1
260 fi 353 fi
261 354
262 TMP_DIR="$(mktemp -d /tmp/crash_sender.XXXX)" 355 TMP_DIR="$(mktemp -d /tmp/crash_sender.XXXX)"
263 356
264 # Send system-wide crashes 357 # Send system-wide crashes
265 send_crashes "/var/spool/crash" 358 send_crashes "/var/spool/crash"
266 359
267 # Send user-specific crashes 360 # Send user-specific crashes
268 send_crashes "/home/chronos/user/crash" 361 send_crashes "/home/chronos/user/crash"
269 } 362 }
270 363
271 main 364 main
OLDNEW
« no previous file with comments | « crash_reporter.cc ('k') | kernel_collector.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698