GNOME Bugzilla – Bug 793494
Cast fd to FILE* before calling fileno
Last modified: 2018-02-16 14:50:02 UTC
FreeBSD sometimes implements fileno as a macro which accesses the member in FILE struct directly. GIMP fails to compile because it passes a void* to fileno. /home/lantw44/gnome/source/gimp/libgimpbase/gimputils.c:1243:52: error: member reference base type 'void' is not a structure or union backtrace_symbols_fd (bt_buf, n_symbols, fileno (fd)); ^~~~~~~~~~~ /usr/include/stdio.h:520:36: note: expanded from macro 'fileno' #define fileno(p) (!__isthreaded ? __sfileno(p) : (fileno)(p)) ^~~~~~~~~~~~ /usr/include/stdio.h:512:26: note: expanded from macro '__sfileno' #define __sfileno(p) ((p)->_file) ~~~^ ~~~~~ 1 error generated. I wonder why a pointer to FILE struct is called 'fd' in gimp_print_stack_trace function. It looks very misleading ... By the way, FreeBSD includes both an ancient GDB (version 6.1) and a modern LLDB (version 4) in the default installation. GIMP prefers GDB to LLDB when generating a stack trace, but the ancient GDB is seldom useful. Tt usually crashes when doing basic things such as running commands or generating backtraces. It is possible to install the latest version of GDB from FreeBSD ports, but the old GDB still comes before the new GDB in PATH. I used 'kill -SEGV gimp-2.9' to test. No dialog was shown and this message was printed on the terminal because of the ancient GDB: Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module /home/lantw44/gnome/devinstall/lib/librsvg-2.so.2] Is it possible to make GIMP ignore the old GDB or prefer LLDB to GDB on FreeBSD?
Created attachment 368386 [details] [review] libgimpbase: Cast fd to FILE* before calling fileno It is required if the system implements fileno as a macro doing direct struct member access.
Thanks. I pushed your commit: commit 7b6756af8eaf6293d3fbe105cd13b6015188a084 Author: Ting-Wei Lan <lantw@src.gnome.org> Date: Fri Feb 16 03:37:21 2018 +0800 libgimpbase: Cast fd to FILE* before calling fileno It is required if the system implements fileno as a macro doing direct struct member access. https://bugzilla.gnome.org/show_bug.cgi?id=793494 libgimpbase/gimputils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (In reply to Ting-Wei Lan from comment #0) > I wonder why a pointer to FILE struct is called 'fd' in > gimp_print_stack_trace function. It looks very misleading ... You are right. This naming is wrong. I just updated it to "stream" instead: commit 9e8e321d62e070b11ed77be027ea0d94f788a0a3 (HEAD -> master, origin/master, origin/HEAD) Author: Jehan <jehan@girinstud.io> Date: Thu Feb 15 21:32:58 2018 +0100 libgimpbase: rename FILE * argument to stream instead of fd. As noted in bug 793494, my naming was unfortunate. A FILE pointer is not a file descriptor (which is why we use fileno() on it). libgimpbase/gimputils.c | 16 ++++++++-------- libgimpbase/gimputils.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) > By the way, FreeBSD includes both an ancient GDB (version 6.1) and a modern > LLDB (version 4) in the default installation. GIMP prefers GDB to LLDB when > generating a stack trace, but the ancient GDB is seldom useful. Tt usually > crashes when doing basic things such as running commands or generating > backtraces. It is possible to install the latest version of GDB from FreeBSD > ports, but the old GDB still comes before the new GDB in PATH. > > I used 'kill -SEGV gimp-2.9' to test. No dialog was shown and this message > was printed on the terminal because of the ancient GDB: > Dwarf Error: wrong version in compilation unit header (is 4, should be 2) > [in module /home/lantw44/gnome/devinstall/lib/librsvg-2.so.2] Could you tell me what this old gdb outputs when running the following: > gdb -batch -ex "backtrace full" /some/running/program 1234 Where you would replace "/some/running/program" and 1234 by a process name and id currently running as your user? Does it output a trace? Some error? Also what is the returned value of this gdb call (echo $0)? > Is it possible to make GIMP ignore the old GDB or prefer LLDB to GDB on > FreeBSD? Would be nice. For ignoring an older gdb, I guess we could make a version check. We could also have some macro check but I'm not sure if the autotools generate a macro to indicate a FreeBSD build (or if we should add such check in configure.ac, then how?). Also I am unsure about such solution. Does not sound very fool-proof to me. I'd prefer a generic solution if possible where we could just switch to the next best thing if the installed GDB is broken.
(In reply to Jehan from comment #2) > > By the way, FreeBSD includes both an ancient GDB (version 6.1) and a modern > > LLDB (version 4) in the default installation. GIMP prefers GDB to LLDB when > > generating a stack trace, but the ancient GDB is seldom useful. Tt usually > > crashes when doing basic things such as running commands or generating > > backtraces. It is possible to install the latest version of GDB from FreeBSD > > ports, but the old GDB still comes before the new GDB in PATH. > > > > I used 'kill -SEGV gimp-2.9' to test. No dialog was shown and this message > > was printed on the terminal because of the ancient GDB: > > Dwarf Error: wrong version in compilation unit header (is 4, should be 2) > > [in module /home/lantw44/gnome/devinstall/lib/librsvg-2.so.2] > > Could you tell me what this old gdb outputs when running the following: > > > gdb -batch -ex "backtrace full" /some/running/program 1234 > > Where you would replace "/some/running/program" and 1234 by a process name > and id currently running as your user? > Does it output a trace? Some error? > Also what is the returned value of this gdb call (echo $0)? It terminates the target process with SIGKILL and exits with status 0. $ /usr/bin/gdb -batch -ex 'backtrace full' gimp-2.9 84681 Error while reading shared library symbols: Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module /home/lantw44/gnome/devinstall/lib/librsvg-2.so.2] 0x0000000806cb958a in _poll () from /lib/libc.so.7 (script-fu:84694): LibGimpBase-WARNING **: 04:50:09.612: script-fu: gimp_wire_read(): error [1]+ Killed gimp-2.9 It is even unable to trace simpler programs such as find, cat, bash. $ /usr/bin/gdb -batch -ex 'backtrace full' find 85002 0x0000000800977d8a in getdirentries () from /lib/libc.so.7 $ /usr/bin/gdb -batch -ex 'backtrace full' cat 84992 0x000000080097e4e8 in _read () from /lib/libc.so.7 $ /usr/bin/gdb -batch -ex 'backtrace full' bash 84962 (no debugging symbols found)...0x0000000800e7692a in _pselect () from /lib/libc.so.7 GDB 8.0 installed from FreeBSD ports works correctly and provides a much better backtrace, but it is neither installed nor used by default. The default PATH puts /usr/bin before /usr/local/bin. >$ /usr/local/bin/gdb -batch -ex 'backtrace full' find 85192 [Switching to LWP 101279 of process 85192] 0x0000000800977d8a in getdirentries () from /lib/libc.so.7
+ Trace 238396
> > Is it possible to make GIMP ignore the old GDB or prefer LLDB to GDB on > > FreeBSD? > > Would be nice. For ignoring an older gdb, I guess we could make a version > check. The old gdb: $ /usr/bin/gdb --version GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, Inc. ... The new gdb: $ /usr/local/bin/gdb --version GNU gdb (GDB) 8.0.1 [GDB v8.0.1 for FreeBSD] Copyright (C) 2017 Free Software Foundation, Inc. ... > We could also have some macro check but I'm not sure if the autotools > generate a macro to indicate a FreeBSD build (or if we should add such check > in configure.ac, then how?). Also I am unsure about such solution. Does not > sound very fool-proof to me. I'd prefer a generic solution if possible where > we could just switch to the next best thing if the installed GDB is broken. Compilers on FreeBSD define __FreeBSD__ macro to the major version of FreeBSD, but yes, it is good to avoid the OS check if a better solution exists.
> Also what is the returned value of this gdb call (echo $0)? Sorry, I meant "echo $?". > Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module /home/lantw44/gnome/devinstall/lib/librsvg-2.so.2] Hmmm… So searching the web about this error, I find this which explains the issue pretty well: https://stackoverflow.com/questions/11671009/dwarf-error-wrong-version-in-compilation-unit-header-is-4-should-be-2 So I don't know much about debugging information format (apparently called DWARF), but from what I get, the problem is that librsvg-2 must have been compiled with -g4, but gdb version 6 only supports up to DWARF 2. It is also confirmed with gcc doc, which says: > Version 4 may require GDB 7.0 and -fvar-tracking-assignments for maximum benefit. > (https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html) So basically it means that it could theoretically work fine on FreeBSD if all the binaries were using up to DWARF 2. Not saying that's an ideal solution, just that blocking older gdb versions may not be the optimal solution either. Also it most likely did not crash, only failed to get the traces and outputted an error, yet returned with 0 (just a guess). Not sure yet what's the best approach.
> It terminates the target process with SIGKILL and exits with status 0. gdb sends a SIGKILL signal to the process it is trying to debug? Seriously? This is a bit fucked-up.
(In reply to Jehan from comment #4) > > Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module /home/lantw44/gnome/devinstall/lib/librsvg-2.so.2] > > Hmmm… So searching the web about this error, I find this which explains the > issue pretty well: > https://stackoverflow.com/questions/11671009/dwarf-error-wrong-version-in- > compilation-unit-header-is-4-should-be-2 > > So I don't know much about debugging information format (apparently called > DWARF), but from what I get, the problem is that librsvg-2 must have been > compiled with -g4, but gdb version 6 only supports up to DWARF 2. It is also > confirmed with gcc doc, which says: > > > Version 4 may require GDB 7.0 and -fvar-tracking-assignments for maximum benefit. > > (https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html) No, I only use -g3 and I don't manually specifies a DWARF version. Objects with DWARF 4 are generated by the rust compiler. > So basically it means that it could theoretically work fine on FreeBSD if > all the binaries were using up to DWARF 2. Not saying that's an ideal > solution, just that blocking older gdb versions may not be the optimal > solution either. > Also it most likely did not crash, only failed to get the traces and > outputted an error, yet returned with 0 (just a guess). > > Not sure yet what's the best approach. It only works when being used interactively. 'backtrace' seems to work. 'backtrace full' works with gimp-2.9 but not cat or find. 'gdb -batch' never works for me. It just prints the first line of the backtrace and terminates the target process. (In reply to Jehan from comment #5) > > It terminates the target process with SIGKILL and exits with status 0. > > gdb sends a SIGKILL signal to the process it is trying to debug? Seriously? > This is a bit fucked-up. I found there was no 'kill' system call after running gdb under ktrace, but there was some difference in the way gdb used ptrace. Interactive gdb called ptrace with PT_DETACH when it exited, but 'gdb -batch' didn't. I guess SIGKILL was sent by the kernel when the process debugging it didn't called ptrace with PT_DETACH before exiting. I could reproduce it by using 'truss -p' to attach to a process and sending SIGKILL to truss. The process traced by truss was terminated with SIGKILL. This old gdb has been removed from FreeBSD 12, the unstable development version. It still exists in the current stable releases, which are 11 and 10. Bugs in this old gdb are not likely to be fixed and users are recommended to use the latest gdb from FreeBSD ports.
I guess adding a version check is probably just the best bet. Still not sure that's ideal, but better than current situation. By the way, does freebsd have this backtrace(), backtrace_symbols() API (execinfo.h), which is our third fallback after gdb/lldb? The `man` says it's a GNU extension to the libc, so I am guessing not. Just to know since I get someone on FreeBSD here. :-)
(In reply to Jehan from comment #7) > I guess adding a version check is probably just the best bet. Still not sure > that's ideal, but better than current situation. I think we can probably ignore GDB version < 7 and find the next GDB or other debuggers in PATH. > By the way, does freebsd have this backtrace(), backtrace_symbols() API > (execinfo.h), which is our third fallback after gdb/lldb? > The `man` says it's a GNU extension to the libc, so I am guessing not. Just > to know since I get someone on FreeBSD here. :-) Yes, we have execinfo.h, but using it requires linking with -lexecinfo. It is already handled by the configure script of GIMP for NetBSD. Link to FreeBSD man page: https://man.freebsd.org/backtrace(3) It says 'the backtrace() library of functions first appeared in NetBSD 7.0 and FreeBSD 10.0.' FreeBSD 10 is the oldest supported release, so I think it is safe to assume backtrace is always available on FreeBSD. However, it is unlikely to find a FreeBSD system which has neither (the ancient) GDB nor (the modern) LLDB. They are not separate packages which users can uninstall but an integral part of the operating system. FreeBSD allows users to disable the installation of debuggers, but it is a build time option, not an installation option that can be found in the installer.
(In reply to Ting-Wei Lan from comment #8) > (In reply to Jehan from comment #7) > > I guess adding a version check is probably just the best bet. Still not sure > > that's ideal, but better than current situation. > > I think we can probably ignore GDB version < 7 and find the next GDB or > other debuggers in PATH. Ow find the next gdb in PATH, that's another issue. I am not really enthusiastic to the idea of adding code inside GIMP scanning PATH just for the debugging tool. It's not hard, just: what is the limit to exceptions in our code for a weird platform choice (why did FreeBSD choose to install an old version of gdb in the first place?!). Especially if you tell me that development version have newer versions of gdb. So I'll probably stop at just discarding the old gdb (and it will go to lldb).
Also I think we are going too much off-topic on this bug report which was about casting to FILE*. That is messy. I just opened a dedicated bug report: bug 793514. The original bug (casting to FILE*) is closed as FIXED.