luncliff/coroutine

crash of channel in clang release

luncliff opened this issue · 2 comments

https://travis-ci.org/luncliff/coroutine/builds/458272794

Note

Debug (with -g) option works as exepected, but Release build yields crash. -O0 option build works well. The crash occurs over -O1 . Seems like optimizer issue.

The testcase is WriteRead, function is write_to. It's weird because its pair ReadWrite test is passed in same build.

Inserting fprintf made the test green. 9b6cc56
Going to check the case with Compiler Explorer

// ensure successful write to channel
template<typename L>
auto write_to(channel<uint64_t, L>& ch, uint64_t value, bool ok = false)
    -> unplug
{
    ok = co_await ch.write(value);

    if (ok == false)
        // inserting fprintf makes the crash disappear.
        // finding the reason for the issue
        fprintf(stdout, "write_to %p %llx \n", &value, value);

    REQUIRE(ok);
}

Releated Feature

  • channel

Compiler / System

  • AppleClang 9.1.0.9020039 / Darwin-17.4.0
  • Clang 6.0.1 / Linux-4.4.0-101-generic (ubuntu)

Can't get the reason, but seems like an optimizer issue.
There was a similar issue in Visual Studio. (looking for the item)

For now, just removed -O2. So there is no difference between debug/release build
db47268

See the comment in the test code bellow. 85ddd61.
Tested with -g -O2.

This issue will be traced for clang 7.0.0 and later version.

template <typename L>
auto write_to(channel<uint64_t, L>& ch, uint64_t value, bool ok = false)
    -> unplug
{
    ok = co_await ch.write(value);
    if (ok == false)
    {
        // inserting fprintf makes the crash disappear.
        // fprintf(stdout, "write_to %p %llx \n", &value, value);

        // !!!!!
        // seems like optimizer is removing `value`.
        // so using it in some pass makes
        // the symbol and its memory location alive
        // !!!!!
        value += 1;
    }
    REQUIRE(ok);
}

template <typename L>
auto read_from(channel<uint64_t, L>& ch, uint64_t& value, bool ok = false)
    -> unplug
{
    std::tie(value, ok) = co_await ch.read();
    REQUIRE(ok);
}