summaryrefslogtreecommitdiff
path: root/test/run_and_catch_crashes
blob: f8b03dd4c1ba04109a288631299de740a2c24203 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#! /bin/sh
#
# Run command in a way that catches crashes
#
# Wireshark - Network traffic analyzer
# By Gerald Combs <gerald@wireshark.org>
# Copyright 2015 Gerald Combs
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Run the command we're passed in a subshell, so that said subshell will
# catch any signals from it and report it.
#
# This must be done for commands that aren't the last command in the
# pipeline, as, given that the exit status of a pipeline is the exit
# status of the last command in the pipeline, there's no guarantee that
# the shell will bother to pick up the exit status of earlier commands
# in the pipeline.
#
# It can also be done for other tests, to get more information than
# "it crashed due to signal XXX" if the tests fail with a crash signal.
#
# XXX - on macOS, core dumps are in /cores/core.{PID}; would they appear
# elsewhere on any other UN*X?
#
rm -f core
"$@"
exitstatus=$?
if [ -r core ]
then
	#
	# Core dumped - try to get a stack trace.
	#
	# First, find the executable.  Skip past env and any env
	# arguments to find the actual executable path.  (If you
	# run a program with an explicit path, and it dumps core,
	# at least on Solaris the output of "file" on the core dump
	# will not give the path, so we don't use that.)
	#
	if [ "$1" = "env" ]
	then
		#
		# Skip past the env command name.
		#
		shift
		#
		# Skip past environment-variable arguments; anything
		# with an "=" in it is an environment-variable argument.
		#
		while expr "$1" : ".*=.*" >/dev/null 2>&1
		do
			shift
		done
echo last expr command was expr "$1" : ".*=.*"
	fi
	if [ -x "$1" ]
	then
		executable="$1"
	else
		executable=`which "$1"`
	fi

	if [ ! -z "$executable" ]
	then
		#
		# Found the executable.
		# Is it a libtool wrapper script?  Look for a .libs
		# directory.
		#
		executable_dirname=`dirname "$executable"`
		if [ -d "$executable_dirname"/.libs ]
		then
			is_libtool_wrapper=yes
		else
			is_libtool_wrapper=no
		fi

		#
		# Now, look for a debugger.
		# XXX - lldb?
		#
		dbx=`which dbx`
		if [ ! -z "$dbx" ]
		then
			#
			# Found dbx.  Run it to get a stack trace;
			# cause the stack trace to go to the standard
			# error.
			#
			if [ $is_libtool_wrapper = yes ]
			then
				$executable_dirname/libtool --mode=execute dbx "$executable" core 1>&2 <<EOF
where
quit
EOF
			else
				dbx "$executable" core 1>&2 <<EOF
where
quit
EOF
			fi
		else
			gdb=`which gdb`
			if [ ! -z "$gdb" ]
			then
				#
				# Found gdb.  Run it to get a stack trace;
				# cause the stack trace to go to the standard
				# error.
				#
				if [ $is_libtool_wrapper = yes ]
				then
					$executable_dirname/libtool --mode=execute gdb "$executable" core 1>&2 <<EOF
backtrace
quit
EOF
				else
					gdb "$executable" core 1>&2 <<EOF
backtrace
quit
EOF
				fi
			fi
		fi
	fi
fi
exit $exitstatus