Bug 2269887

Summary: [abrt] cscope: _IO_deallocate_file(): cscope killed by SIGABRT
Product: [Fedora] Fedora Reporter: Jeff Frontz <jeff.frontz>
Component: cscopeAssignee: Vladis Dronov (Fedora) <vdronoff+fedora>
Status: CLOSED ERRATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 39CC: contribs, jeff.frontz, vdronoff+fedora, vdronov
Target Milestone: ---Keywords: Reopened
Target Release: ---   
Hardware: x86_64   
OS: Unspecified   
URL: https://retrace.fedoraproject.org/faf/reports/bthash/007d6534db018e9fa07edc6e882a8d928d16662
Whiteboard: abrt_hash:11b7d276ffd736b84350de78005bf2a517c7e110;VARIANT_ID=workstation;
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2024-08-05 14:33:55 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
File: mountinfo
none
File: environ
none
File: core_backtrace
none
File: backtrace
none
File: limits
none
File: proc_pid_status
none
File: cpuinfo
none
File: os_info
none
File: dso_list
none
File: maps
none
File: open_fds none

Description Jeff Frontz 2024-03-16 20:57:26 UTC
Description of problem:
no idea

Version-Release number of selected component:
cscope-15.9-19.fc39

Additional info:
reporter:       libreport-2.17.11
type:           CCpp
cmdline:        cscope -q
crash_function: _IO_deallocate_file
comment:        no idea
journald_cursor: s=324a1cb18b6e4ea484c4979592d25d78;i=6ecf2;b=ccf88b0373ef4caf9e48189be29ae9a9;m=29c47e32b71;t=613cd58b38236;x=bc81f54913b5ea21
executable:     /usr/bin/cscope
rootdir:        /
uid:            1000
kernel:         6.6.13-200.fc39.x86_64
package:        cscope-15.9-19.fc39
runlevel:       N 5
cgroup:         0::/user.slice/user-1000.slice/session-280.scope
reason:         cscope killed by SIGABRT
backtrace_rating: 4

Truncated backtrace:
Thread no. 1 (4 frames)
 #8 _IO_deallocate_file at /usr/src/debug/glibc-2.38-16.fc39.x86_64/libio/libioP.h:958
 #10 myexit at /usr/src/debug/cscope-15.9-19.fc39.x86_64/src/main.c:1062
 #12 __unlink at ../sysdeps/unix/sysv/linux/unlink.c:28
 #13 myexit at /usr/src/debug/cscope-15.9-19.fc39.x86_64/src/main.c:1066

Comment 1 Jeff Frontz 2024-03-16 20:57:29 UTC
Created attachment 2021990 [details]
File: mountinfo

Comment 2 Jeff Frontz 2024-03-16 20:57:30 UTC
Created attachment 2021991 [details]
File: environ

Comment 3 Jeff Frontz 2024-03-16 20:57:31 UTC
Created attachment 2021992 [details]
File: core_backtrace

Comment 4 Jeff Frontz 2024-03-16 20:57:33 UTC
Created attachment 2021993 [details]
File: backtrace

Comment 5 Jeff Frontz 2024-03-16 20:57:34 UTC
Created attachment 2021994 [details]
File: limits

Comment 6 Jeff Frontz 2024-03-16 20:57:35 UTC
Created attachment 2021995 [details]
File: proc_pid_status

Comment 7 Jeff Frontz 2024-03-16 20:57:37 UTC
Created attachment 2021996 [details]
File: cpuinfo

Comment 8 Jeff Frontz 2024-03-16 20:57:38 UTC
Created attachment 2021997 [details]
File: os_info

Comment 9 Jeff Frontz 2024-03-16 20:57:39 UTC
Created attachment 2021998 [details]
File: dso_list

Comment 10 Jeff Frontz 2024-03-16 20:57:40 UTC
Created attachment 2021999 [details]
File: maps

Comment 11 Jeff Frontz 2024-03-16 20:57:41 UTC
Created attachment 2022000 [details]
File: open_fds

Comment 12 Vladis Dronov 2024-07-30 21:12:49 UTC
it looks like cscope was killed by SIGABRT, presumably, at container exit. cscope itself looks ok.

> abort() is usually called by library functions which detect an internal error or some seriously
> broken constraint. For example malloc() will call abort() if its internal structures are damaged
> by a heap overflow.

Comment 13 Jeff Frontz 2024-07-31 16:30:02 UTC
> container exit

I'm not sure what you mean by "container", but just in case: this was being run via an interactive shell on the base OS (no docker, etc. involved).

Comment 14 Jeff Frontz 2024-07-31 16:31:01 UTC
*** Bug 2256515 has been marked as a duplicate of this bug. ***

Comment 15 Vladis Dronov 2024-08-04 15:03:09 UTC
so a research shows that the cscope process attempted a normal exit (by "q" or Ctrl-D) calling myexit(0).
in the middle of it a signal SIGHUP handler was called, which is myexit() itself. then glibc detects a
double-free condition in __GI___libc_free() while performing fclose(refsfound). then glibc aborts the process
with __GI_abort() and the "free(): double free detected in tcache 2" message. backtraces we have are:

main.c:847 in main(): /* normal quit */ myexit(0); ->
  main.c:1079 in myexit(sig=0): freefilelist(); ->
    dir.c:727 in in freefilelist(): free(srcfiles[--nsrcfiles]); ->
      malloc.c:3352 in __GI___libc_free() ->
        <signal handler called> ->
          main.c:1062 in myexit (sig=1 SIGHUP ): fclose(refsfound); ->
            iofclose.c:74 in _IO_new_fclose() -> ... ->
              malloc.c:3391 in __GI___libc_free() ->
                malloc_printerr("free(): double free detected in tcache 2") -> __GI_abort()

main.c:847 in main(): /* normal quit */ myexit(0); ->
  main.c:1066 in myexit(sig=0): unlink(temp1); ->
    unlink.c:28 __unlink (name=<temp1> "/tmp/cscope.699047/cscope.1"); ->
      <signal handler called> ->
        main.c:1062 in myexit (sig=1 SIGHUP ): fclose(refsfound); ->
          iofclose.c:74 in _IO_new_fclose() -> ... ->
            malloc.c:3391 in __GI___libc_free() ->
              malloc_printerr("free(): double free detected in tcache 2") -> __GI_abort()

in a short word, a process abort is caused by myexit() interrupted by a signal which handler is myexit() itself. 

note, free() and fclose() are NOT async-signal-safe, see "man 7 signal-safety". calling an async-signal-unsafe
function from a signal handler is perfectly legal unless the signal interrupted another async-signal-unsafe function.
so i'm not sure about the unlink() case, unlink() is async-signal-safe. still, the double-free condition is still
there, as we can see from the backtrace.

i'm not going to fix the whole signal handling in cscope, as it is broken. 1) myexit() calls functions which are
not async-signal-safe 2) signal() infrastructure (which is broken) is used instead of sigaction(). i'll fix only
this specific case where myexit() is interrupted by a call to myexit() itself by resetting signal handlers to
default ones. this may be not entirely correct but whatever.