After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 793494 - Cast fd to FILE* before calling fileno
Cast fd to FILE* before calling fileno
Status: RESOLVED FIXED
Product: GIMP
Classification: Other
Component: General
git master
Other FreeBSD
: Normal normal
: 2.10
Assigned To: GIMP Bugs
GIMP Bugs
Depends on:
Blocks:
 
 
Reported: 2018-02-15 19:36 UTC by Ting-Wei Lan
Modified: 2018-02-16 14:50 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
libgimpbase: Cast fd to FILE* before calling fileno (1004 bytes, patch)
2018-02-15 19:39 UTC, Ting-Wei Lan
none Details | Review

Description Ting-Wei Lan 2018-02-15 19:36:41 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?
Comment 1 Ting-Wei Lan 2018-02-15 19:39:25 UTC
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.
Comment 2 Jehan 2018-02-15 20:44:40 UTC
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.
Comment 3 Ting-Wei Lan 2018-02-15 21:17:24 UTC
(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
  • #0 getdirentries
    from /lib/libc.so.7
  • #1 _readdir_unlocked
    at /usr/src/lib/libc/gen/readdir.c line 69
  • #2 fts_build
    at /usr/src/lib/libc/gen/fts.c line 739
  • #3 fts_read
    at /usr/src/lib/libc/gen/fts.c line 389
  • #4 find_execute
    at /usr/src/usr.bin/find/find.c line 208
  • #5 main
    at /usr/src/usr.bin/find/main.c line 158

> > 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.
Comment 4 Jehan 2018-02-15 21:23:37 UTC
> 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.
Comment 5 Jehan 2018-02-15 21:26:28 UTC
> 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.
Comment 6 Ting-Wei Lan 2018-02-16 07:22:32 UTC
(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.
Comment 7 Jehan 2018-02-16 13:05:49 UTC
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. :-)
Comment 8 Ting-Wei Lan 2018-02-16 13:42:46 UTC
(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.
Comment 9 Jehan 2018-02-16 14:46:23 UTC
(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).
Comment 10 Jehan 2018-02-16 14:50:02 UTC
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.