The code is definitely wrong in making non-async-signal-safe calls in
a signal handler. The signal handlers should set some flag and let the
main loop know that it should exit.

--Elad

On Tue, Aug 6, 2024 at 8:45 AM Vladis Dronov <vdro...@redhat.com> wrote:
>
> i know this is a dead list, so i'm sorry for a necro posting into a gray
> void.
>
> still, we see cscope aborts at exit due to myexit() recursive call. we have
> 2 cases, see backtraces attached
> (i have no idea if this list@ accepts these attachments). also see the
> following for details:
>
> https://bugzilla.redhat.com/show_bug.cgi?id=2269887#c15 - research
> - an ugly fix
>
> 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.
>
> Best regards,
> Vladis
>
> ---
>
> diff -up ./src/main.c.orig ./src/main.c
> --- ./src/main.c.orig 2024-08-04 16:49:08.723525637 +0200
> +++ ./src/main.c 2024-08-04 16:53:19.967862016 +0200
> @@ -1056,11 +1056,18 @@ Please see the manpage for more informat
>  void
>  myexit(int sig)
>  {
> + /* reset signal handlers to default ones, so myexit() is not called
> + * recursively as a signal handler during a normal exit */
> + signal(SIGINT, SIG_DFL);
> + signal(SIGQUIT, SIG_DFL);
> + signal(SIGHUP, SIG_DFL);
> + signal(SIGTERM, SIG_DFL);
> +
>   /* HBB 20010313; close file before unlinking it. Unix may not care
>   * about that, but DOS absolutely needs it */
>   if (refsfound != NULL)
>   fclose(refsfound);
> -
> +
>   /* remove any temporary files */
>   if (temp1[0] != '\0') {
>   unlink(temp1);
> _______________________________________________
> Cscope-devel mailing list
> Cscope-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/cscope-devel


_______________________________________________
Cscope-devel mailing list
Cscope-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/cscope-devel

Reply via email to