https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119916

Zartaj Majeed <zmajeed at sbcglobal dot net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |zmajeed at sbcglobal dot net

--- Comment #22 from Zartaj Majeed <zmajeed at sbcglobal dot net> ---
Thank you for the quick fix.
I ran into this bug recently with gcc 15.1 - didn't occur to me to check
bugzilla right away - but was very happy to find it reported and fixed already!

I verified the fix on master with this little program below - but I wonder if
someone could explain an additional difference in behavior I'm seeing

----------------------------
// int_coroutine.cpp

#include <coroutine>
#include <print>

using namespace std;

struct Tag {};

struct IntRO {

  struct promise_type {

    int result = -999;

    auto get_return_object() noexcept {
      return IntRO{coroutine_handle<promise_type>::from_promise(*this)};
    }

    suspend_never initial_suspend() noexcept {
      return {};
    }

    suspend_always final_suspend() noexcept {
      return {};
    }

    void return_value(int x) noexcept {
      result = x;
    }

    void unhandled_exception() noexcept {
    }

  };

  operator int() {
    return coro.promise().result;
  }

#if NO_CORO_CHECK
  ~IntRO() {
    coro.destroy();
  }
#else
  ~IntRO() {
    if(coro.done()) {
      coro.destroy();
    }
  }
#endif

  coroutine_handle<promise_type> coro;
};

template<>
struct std::coroutine_traits<int, Tag> {
  using promise_type = IntRO::promise_type;
};

int main() {

  auto result = [](Tag) static -> int {
    co_return 13;
  }({});

  println("main: int coroutine returned {}, expected 13", result);
  return result == 13? 0: 1;
}
----------------------------

With installed GCC 15.1.1

g++ -dumpfullversion && g++ -std=c++26 -o int_coroutine.gcc15 int_coroutine.cpp
&& ./int_coroutine.gcc15

15.1.1
main: int coroutine returned -999, expected 13

With GCC built from master

build/g++ -dumpfullversion && build/g++ -std=c++26 -o int_coroutine.gcc16
int_coroutine.cpp && ./int_coroutine.gcc16

16.0.0
IntRO.destructor: destroy own coro 0xa000165c0
main: int coroutine returned 13, expected 13

----------------------------

The extra difference is when InRO destructor runs with GCC from master,
coro.done() returns true and coro.destroy() succeeds

But for GCC 15.1.1, coro.done() returns false and coro.destroy() is not called
- indeed removing the check and calling coro.destroy() unconditionally causes a
SIGABRT crash

There is no crash with GCC from master when coro.destroy() is called
unconditionally

----------------------------

g++-15 -dumpfullversion && g++-15 -std=c++26 -DNO_CORO_CHECK -o
int_coroutine.nocheck.gcc15 int_coroutine.cpp && ./int_coroutine.nocheck.gcc15

15.1.1
free(): double free detected in tcache 2
Aborted (core dumped)

Stack trace in gdb

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>) at
./nptl/pthread_kill.c:44

#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>)
at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=<optimized out>) at
./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6) at
./nptl/pthread_kill.c:89
#3  0x00007ffff784527e in __GI_raise (sig=sig@entry=6) at
../sysdeps/posix/raise.c:26
#4  0x00007ffff78288ff in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff78297b6 in __libc_message_impl (fmt=fmt@entry=0x7ffff79ce8d7
"%s\n") at ../sysdeps/posix/libc_fatal.c:134
#6  0x00007ffff78a8ff5 in malloc_printerr (str=str@entry=0x7ffff79d1bf0
"free(): double free detected in tcache 2") at ./malloc/malloc.c:5772
#7  0x00007ffff78ab55f in _int_free (av=0x7ffff7a03ac0 <main_arena>,
p=<optimized out>, have_lock=0) at ./malloc/malloc.c:4541
#8  0x00007ffff78addae in __GI___libc_free (mem=0x55555558f2b0) at
./malloc/malloc.c:3398
#9  0x0000555555558ab5 in operator() (frame_ptr=0x55555558f2b0) at
int_coroutine.cpp:66
#10 0x00005555555588be in operator() () at int_coroutine.cpp:64
#11 0x0000555555558b2a in main () at int_coroutine.cpp:66

Reply via email to