Project

General

Profile

Debugging » History » Version 21

Jaroslav Kysela, 2017-06-06 17:29

1 1 Adam Sutton
h1. Debugging
2
3 20 Jaroslav Kysela
If you use the packaged version of tvheadend, make sure that you use the debug version of tvheadend (with the debugging symbols). For debian/ubuntu these packages have *_dbg* suffix, for rpm packages, these symbols are in *debuginfo* rpm files.
4 19 Jaroslav Kysela
5 1 Adam Sutton
If you're going to be regularly trying development versions of Tvheadend or need to report a crash or deadlock then you should really read this page!
6
7 7 Jaroslav Kysela
If you are investigating problems within Tvheadend then its worth being familiar with tools such as gdb and valgrind or clang, although these are not covered here.
8 1 Adam Sutton
9
However one thing that can be useful in investigating crashes within Tvheadend is to ensure that coredumps are generated, this will allow post analysis in gdb without having to actual run Tvheadend within gdb.
10
11
You can enable temporarily by running:
12
13
<pre>
14
ulimit -c unlimited
15
</pre>
16
17
To make this permanent put this somewhere in your shell environment setup (.bashrc, .profile, etc...)
18
Firstly I'd recommend that if you're specifically trying to investigate an issue then you should consider running Tvheadend manually, rather than as a service, as documented [[Development|here]].
19
20
h2. Logging
21
22
I'd strongly recommend that if you're specifically trying to investigate a crash or other problem in Tvheadend that you enable debugging:
23
24
* *-s* will output debug info to syslog
25
* *--debug* allows you to specify which subsystem to debug (TODO: add more info)
26
* *--trace* allows you to enable trace (more in-depth) logging on specific subsystems
27
28
You can also get Tvheadend to log to it's own file using:
29
30
<pre>
31
-l FILE
32
</pre>
33
34 2 Jaroslav Kysela
You may also modify the debug settings using WEB GUI as admin - Configuration/Debugging. Note that the information is not saved,
35
it is just set for run-time (current task).
36
37
* Debug log path - filename to store log
38
* Debug trace - enable traces
39
* Debug subsystems - comma separated list of subsystems
40
* Trace subsystems - comma separated list of subsystems
41
42 3 Jaroslav Kysela
The traces must be compiled to the tvheadend binary - see [[Traces]].
43 2 Jaroslav Kysela
44 21 Jaroslav Kysela
h2. Incorrect (not useable) crash reports
45
46
<pre>
47
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: Signal: 11 in PRG: /usr/bin/tvheadend (4.3-193~ga4ff519) [15a15a895adaf9c5760b80707f582c2d60cfab01] CWD: /
48
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: Fault address 0x90 (Address not mapped)
49
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: STACKTRACE
50
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: ??:0 0x555558549eba 0x555558350000
51
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: ??:0 0x7f3d97c0c0c0 0x7f3d97bfb000
52
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: ??:0 0x555558525620 0x555558350000
53
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: ??:0 0x5555585257a8 0x555558350000
54
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: ??:? 0x5555585db371 0x555558350000
55
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: ??:? 0x5555585dc1f2 0x555558350000
56
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: ??:? 0x5555585c3212 0x555558350000
57
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: ??:? 0x5555585bb71d 0x555558350000
58
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: ??:? 0x5555585bb8d1 0x555558350000
59
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: ??:0 0x5555585b4589 0x555558350000
60
Jun  6 15:01:08 plantage tvheadend[10808]: CRASH: ??:0 0x5555585b4796 0x555558350000
61
Jun  6 15:01:09 plantage tvheadend[10808]: CRASH: ??:0 0x555558511e44 0x555558350000
62
Jun  6 15:01:09 plantage tvheadend[10808]: CRASH: ??:0 0x7f3d97c02494 0x7f3d97bfb000
63
Jun  6 15:01:09 plantage kernel: [2320412.837462] tvh:mi-table[11208]: segfault at 90 ip 0000555558525620 sp 00007f3d85ff0b98 error 4 in tvheadend[555558350000+10d1000]
64
</pre>
65
66
In this case, the debug symbols are missing (look to the top of this page).
67
68 4 Jaroslav Kysela
h2. Basic crash debug
69
70
You may run tvh in gdb directly using command:
71
72
<pre>
73
gdb --args /the standard tvh command line/
74 5 Jaroslav Kysela
75
(gdb) run
76 4 Jaroslav Kysela
</pre>
77
78
Or attach gdb to the running process:
79
80
<pre>
81
gdb tvheadend pid
82 5 Jaroslav Kysela
83
(gdb) continue
84 4 Jaroslav Kysela
</pre>
85
86 17 Jaroslav Kysela
The 'continue' command will continue the execution of the program. If you need to _break_ the execution and return to gdb, just use 'Ctrl-C'.
87
88 4 Jaroslav Kysela
You may need to replace _tvheadend_ with the full path to the binary and you will need to replace _pid_ with the PID of the running process. To find that run:
89
90
<pre>
91
ps -C tvheadend
92
</pre>
93
94
Once you have gdb attached grab a stack trace from every thread using the following command:
95
96
<pre>
97
(gdb) set logging on
98
(gdb) set pagination off
99
(gdb) bt full
100
</pre>
101
102
Note: "set logging on" will cause GDB to write its output to a file, by default this will be gdb.txt in the current directory.
103
104 1 Adam Sutton
h2. Enabling coredumps
105
106 4 Jaroslav Kysela
If you need to investigate some running problem you can always attach (see below) later and if you need to trap crashes, then you can configure your system to generate a core file and then retrospectively analyse this with gdb.
107 1 Adam Sutton
108
If you're running manually you should enable coredumps in your environment:
109
110
<pre>
111
ulimit -c unlimited
112
</pre>
113
114
I'd recommend you enable this permanently by putting this command in your shell initialisation scripts (.bashrc etc..).
115
116
If you're running as a daemon then you should use the -D command line option, this will enable coredumps from the daemon. If you start using sysvinit, upstart etc... then you will need to put this in the configuration file, e.g.:
117
118
<pre>
119
TVH_ARGS="-D"
120
</pre>
121
122
Finally it's probably worth changing the coredump file format, personally I use the following configuration:
123
124
<pre>
125
echo core.%h.%e.%t | sudo tee /proc/sys/kernel/core_pattern
126
echo 0 | sudo tee /proc/sys/kernel/core_uses_pid
127
</pre>
128
129
Or put the following in /etc/sysctl.conf:
130
131
<pre>
132
kernel.core_pattern = core.%h.%e.%t
133
kernel.core_uses_pid = 0
134
</pre>
135
136
If you're using a system like Ubuntu that uses apport (and cripples the ability to change the core format) just set core_uses_pid=1 instead.
137
138
Note: coredumps are (by default) stored in the current working directory, to make it possible for the daemon to write files the current working directory is set to /tmp when using -D, so check there for core files.
139
140
To verify that you have everything configured properly you can use the -A option to force a crash on startup. Do this from the command line or add to /etc/default/tvheadend:
141
142
<pre>
143
TVH_ARGS="-D -A"
144
</pre>
145
146
Note: remember to remove the option after you've tested it!
147
148
h2. Processing core file.
149
150
Once you have a core file you can start up gdb with that coredump, just as if you'd caught the crash while running under gdb:
151
152
<pre>
153
gdb tvheadend core
154
</pre>
155
156
You may need to replace _tvheadend_ and _core_ above with the proper paths.
157
158
For most crashes the most useful information is the back trace, this will provide a stack trace showing where the code crashed and the stack information at the time of the crash:
159
160
<pre>
161
(gdb) set logging on
162
(gdb) set pagination off
163
(gdb) bt full
164
#0  0x00007f5b10cc1425 in __GI_raise (sig=<optimised out>)
165
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
166
        resultvar = 0
167
        pid = <optimised out>
168
        selftid = 7517
169
#1  0x00007f5b10cc4b10 in __GI_abort () at abort.c:120
170
        act = {__sigaction_handler = {sa_handler = 0, sa_sigaction = 0}, 
171
          sa_mask = {__val = {18446744073709551615 <repeats 16 times>}}, 
172
          sa_flags = 0, sa_restorer = 0}
173
        sigs = {__val = {32, 0 <repeats 15 times>}}
174
#2  0x000000000040744e in main (argc=<optimised out>, argv=<optimised out>)
175
    at src/main.c:810
176
        i = <optimised out>
177
        set = {__val = {16386, 0 <repeats 15 times>}}
178
        adapter_mask = <optimised out>
179
        log_level = <optimised out>
180
        log_options = <optimised out>
181
        log_debug = <optimised out>
182
        log_trace = <optimised out>
183
        buf = "/tmp\000\000\000\000\360\350\364\023[\177\000\000\000\320\365\023[\177\000\000t\n\327\023[\177\000\000\370\271\311\020[\177\000\000\017\000\000\000\000\000\000\000:\000\000\000\000\000\000\000h\344\364\023[\177\000\000.N=\366\000\000\000\000\236\022\327\023[\177\000\000\300\304S\205\377\177\000\000.\000\000\000\000\000\000\000 \305S\205\377\177\000\000\377\377\377\377\000\000\000\000\264\352\310\020[\177\000\000\250\354\310\020[\177\000\000\360\304S\205\377\177\000\000\360\350\364\023[\177\000\000@\256\311\020[\177", '\000' <repeats 18 times>"\340, \346\364\023[\177\000\000\000\320\365\023[\177\000\000\231,@\000\000\000\000\000\370\271\311\020[\177\000\000\340\033@\000\000\000\000\000\000\000\000\000\001\000\000\000\021\b\000\000\001", '\000' <repeats 11 times>, " \266\370\023[\177\000\000`\305S\205\377\177\000\000.N=\366\000\000\000\000\340\346\364\023[\177\000\000\200\305S\205\377\177\000\000"...
184
        opt_help = 0
185
        opt_version = 0
186
        opt_fork = 1
187
        opt_firstrun = 0
188
        opt_stderr = 0
189
        opt_syslog = 0
190
        opt_uidebug = 0
191
</pre>
192
193
Note: "set logging on" will cause GDB to write its output to a file, by default this will be gdb.txt in the current directory.
194
195
However I'd strongly recommend that you keep a copy of tvheadend binary and core file in case further analysis is required.
196
197
h2. Dead or Live Lock
198
199
If Tvheadend appears to die but the process is still running, then its quite possible that the process is deadlocked (or possibly live locked). The best way to help investigate such a problem is to get a full stack trace from every thread in the system.
200
201
First attach gdb to the running process:
202
203
<pre>
204
gdb tvheadend pid
205 5 Jaroslav Kysela
206
(gdb) continue
207 1 Adam Sutton
</pre>
208 17 Jaroslav Kysela
209 18 Jaroslav Kysela
The 'continue' command will continue the execution of the program. If you need to _break_ the execution and return to gdb, just use 'Ctrl-C'.
210 1 Adam Sutton
211
You may need to replace _tvheadend_ with the full path to the binary and you will need to replace _pid_ with the PID of the running process. To find that run:
212
213
<pre>
214
ps -C tvheadend
215
</pre>
216
217
Once you have gdb attached grab a stack trace from every thread using the following command:
218
219
<pre>
220
(gdb) set logging on
221
(gdb) set pagination off
222
(gdb) thread apply all bt full
223
</pre>
224
225
Note: "set logging on" will cause GDB to write its output to a file, by default this will be gdb.txt in the current directory.
226
227
It might also be useful to generate a core file for good measure:
228
229
<pre>
230
(gdb) generate-core-file
231
</pre>
232
233
This information may give an indication as to why things are locked, often 2 threads are stuck trying to lock a mutex (probably each holds the opposite lock).
234
235
h2. Reporting crash (or lock)
236
237 6 Jaroslav Kysela
If you're going to report a crash (or lockup) then please try to provide the above information, including a debug log (or whatever logging you have), a core file and the tvheadend binary and basic information about the platform (distribution, version and architecture) you're running on.
238 8 Jaroslav Kysela
239
h1. Memory leaks or corruption
240
241
It may be really difficult to track these problems. There are basically two tools which may help to discover the memory leaks or memory corruptions.
242
243
h2. Valgrind
244
245
It is very slow, but it may be useable for things which are triggered everytime:
246
247
<pre>
248
valgrind --leak-check=full --show-reachable=yes /tvh_command_line/
249
</pre>
250
251
h2. clang
252
253 9 Jaroslav Kysela
There is address sanitizer in the clang toolkit. The binary must be rebuild using the clang compiler and libraries:
254 8 Jaroslav Kysela
255
<pre>
256
ARGS="/your_configure_arguments/"
257
SANITIZER=address
258
export CFLAGS="-fsanitize=$SANITIZER"
259
export LDFLAGS="-fsanitize=$SANITIZER"
260
./configure $ARGS --disable-pie --enable-ccdebug python=python3 cc=clang ld=clang nowerror
261
make -j4
262
</pre>
263 10 C K
264
Example build script (build_with_clang.sh):
265
266
<pre>
267
#!/bin/sh
268 16 C K
make distclean
269 10 C K
ARGS="--enable-libffmpeg_static --disable-hdhomerun_static"
270
SANITIZER=address
271
export CFLAGS="-fsanitize=$SANITIZER"
272
export LDFLAGS="-fsanitize=$SANITIZER"
273 11 C K
./configure $ARGS --disable-pie --enable-ccdebug python=python3 cc=clang ld=clang nowerror
274 10 C K
make -j4
275
</pre>
276
277
Make sure to make your script executable.
278 12 Jaroslav Kysela
279
If you do not see resolved the function names like:
280
281
<pre>
282
==16673==WARNING: Trying to symbolize code, but external symbolizer is not initialized!
283
    #0 0x7fcda9407680 (/home/tvh/src/tvheadend/build.linux/tvheadend+0x65b680)
284
    #1 0x7fcda943b115 (/home/tvh/src/tvheadend/build.linux/tvheadend+0x68f115)
285
</pre>
286
287 16 C K
get the correct path for the llvm-symbolizer, i.e. with 
288
<pre>whereis llvm-symbolizer</pre>
289
290 12 Jaroslav Kysela
then make sure that you set the external symbolizer like:
291
292 1 Adam Sutton
<pre>
293 16 C K
ASAN_OPTIONS=symbolize=1 ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer /home/ts/workspace/tvheadend/build.linux/tvheadend -l thv.log
294 13 Jaroslav Kysela
</pre>
295
296
The error log should be like:
297
298
<pre>
299 14 Jaroslav Kysela
==27911==ERROR: AddressSanitizer: heap-use-after-free on address 0x60700000d928 at pc 0x56409f916af4 bp 0x7ffc463d6670 sp 0x7ffc463d6668
300
READ of size 8 at 0x60700000d928 thread T0
301 15 Jaroslav Kysela
    #0 0x56409f916af3 in idnode_unlink /home/tvh/git/tvheadend/src/idnode.c:164:94
302
    #1 0x56409f9c9f8a in memoryinfo_unregister /home/tvh/git/tvheadend/src/memoryinfo.h:52:3
303
    #2 0x56409f9c9de2 in streaming_done /home/tvh/git/tvheadend/src/streaming.c:597:3
304 12 Jaroslav Kysela
</pre>