When I use co_spawn across multiple modules and enable optimization levels O2 or O3, I encounter a linker error during the linking phase. It appears that the compiler discards some symbols it deems unused during the linking stage.
Minimal reproduce code
ctx.h
#pragma once
#include <boost/asio/io_context.hpp>
extern boost::asio::io_context io_context_;`
ctx.cpp
#include "ctx.h"
boost::asio::io_context io_context_;
test_link.h
#pragma once
#include <boost/asio/awaitable.hpp>
#include "ctx.h"
boost::asio::awaitable<int> test_link1();
boost::asio::awaitable<void> test_link();
test_link.cpp
#include "test_link.h"
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
boost::asio::awaitable<int> test_link1() { co_return 0; }
boost::asio::awaitable<void> test_link() {
boost::asio::co_spawn(io_context_, test_link1(), boost::asio::detached);
co_return;
}
test_linka.h
#pragma once
#include <boost/asio/awaitable.hpp>
boost::asio::awaitable<int> test_linka1();
boost::asio::awaitable<void> test_linka();
test_linka.cpp
#include "test_linka.h"
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include "ctx.h"
boost::asio::awaitable<int> test_linka1() { co_return 0; }
boost::asio::awaitable<void> test_linka() {
boost::asio::co_spawn(io_context_, test_linka1(), boost::asio::detached);
co_return;
}
main.cpp
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/signal_set.hpp>
#include "ctx.h"
#include "test_link.h"
#include "test_linka.h"
int main() {
try {
boost::asio::signal_set signals(io_context_, SIGINT, SIGTERM);
signals.async_wait([&](auto, auto) { io_context_.stop(); });
boost::asio::co_spawn(io_context_, test_link(), boost::asio::detached);
boost::asio::co_spawn(io_context_, test_linka(), boost::asio::detached);
io_context_.run();
} catch (std::exception& e) {
// exception
}
return 0;
}
My development environment
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/opt/rh/gcc-toolset-13/root/usr/libexec/gcc/x86_64-redhat-linux/13/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/opt/rh/gcc-toolset-13/root/usr --mandir=/opt/rh/gcc-toolset-13/root/usr/share/man --infodir=/opt/rh/gcc-toolset-13/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --enable-libstdcxx-backtrace --with-libstdcxx-zoneinfo=/opt/rh/gcc-toolset-13/root/usr/share/zoneinfo --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-13.1.1-20230614/obj-x86_64-redhat-linux/isl-install --enable-offload-targets=nvptx-none --without-cuda-driver --enable-offload-defaulted --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.1.1 20230614 (Red Hat 13.1.1-4) (GCC)
Compilation
g++ -c -x c++ /home/duanyu/projects/asio/ctx.cpp -I "/home/duanyu/sk-server-base/include" -g1 -o "/home/duanyu/projects/asio/obj/x64/Release/ctx.o" -Wall -Wswitch -W"no-deprecated-declarations" -W"empty-body" -Wconversion -W"return-type" -Wparentheses -W"no-format" -Wuninitialized -W"unreachable-code" -W"unused-function" -W"unused-value" -W"unused-variable" -O3 -fno-strict-aliasing -fomit-frame-pointer -DBOOST_ASIO_HAS_STD_COROUTINE -DBOOST_ASIO_HAS_CO_AWAIT -DNDEBUG -DNDEBUG -fthreadsafe-statics -fexceptions -frtti -std=c++20 -fno-inline
g++ -c -x c++ /home/duanyu/projects/asio/main.cpp -I "/home/duanyu/sk-server-base/include" -g1 -o "/home/duanyu/projects/asio/obj/x64/Release/main.o" -Wall -Wswitch -W"no-deprecated-declarations" -W"empty-body" -Wconversion -W"return-type" -Wparentheses -W"no-format" -Wuninitialized -W"unreachable-code" -W"unused-function" -W"unused-value" -W"unused-variable" -O3 -fno-strict-aliasing -fomit-frame-pointer -DBOOST_ASIO_HAS_STD_COROUTINE -DBOOST_ASIO_HAS_CO_AWAIT -DNDEBUG -DNDEBUG -fthreadsafe-statics -fexceptions -frtti -std=c++20 -fno-inline
g++ -c -x c++ /home/duanyu/projects/asio/test_link.cpp -I "/home/duanyu/sk-server-base/include" -g1 -o "/home/duanyu/projects/asio/obj/x64/Release/test_link.o" -Wall -Wswitch -W"no-deprecated-declarations" -W"empty-body" -Wconversion -W"return-type" -Wparentheses -W"no-format" -Wuninitialized -W"unreachable-code" -W"unused-function" -W"unused-value" -W"unused-variable" -O3 -fno-strict-aliasing -fomit-frame-pointer -DBOOST_ASIO_HAS_STD_COROUTINE -DBOOST_ASIO_HAS_CO_AWAIT -DNDEBUG -DNDEBUG -fthreadsafe-statics -fexceptions -frtti -std=c++20 -fno-inline
g++ -c -x c++ /home/duanyu/projects/asio/test_linka.cpp -I "/home/duanyu/sk-server-base/include" -g1 -o "/home/duanyu/projects/asio/obj/x64/Release/test_linka.o" -Wall -Wswitch -W"no-deprecated-declarations" -W"empty-body" -Wconversion -W"return-type" -Wparentheses -W"no-format" -Wuninitialized -W"unreachable-code" -W"unused-function" -W"unused-value" -W"unused-variable" -O3 -fno-strict-aliasing -fomit-frame-pointer -DBOOST_ASIO_HAS_STD_COROUTINE -DBOOST_ASIO_HAS_CO_AWAIT -DNDEBUG -DNDEBUG -fthreadsafe-statics -fexceptions -frtti -std=c++20 -fno-inline
Link
g++ -o "/home/duanyu/projects/asio/bin/x64/Release/asio.out" -Wl,--no-undefined -Wl,-L"/home/duanyu/sk-server-base/lib/boost/release" -Wl,-L"/home/duanyu/sk-server-base/lib/tclog/release" -Wl,-L"/home/duanyu/sk-server-base/lib/log4cplus/release" -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack /home/duanyu/projects/asio/obj/x64/Release/ctx.o /home/duanyu/projects/asio/obj/x64/Release/main.o /home/duanyu/projects/asio/obj/x64/Release/test_link.o /home/duanyu/projects/asio/obj/x64/Release/test_linka.o -llog4cplus -ltclog -lboost_system -lboost_thread -lboost_date_time -lboost_regex -lboost_serialization -lboost_context -lpthread
ErrorInfo
`_ZN5boost4asio6detail20co_spawn_entry_pointEPZNS1_20co_spawn_entry_pointIiNS1_16detached_handlerENS0_15any_io_executorENS1_21awaitable_as_functionIiS4_EEEENS0_9awaitableINS1_28awaitable_thread_entry_pointET1_EEPNS7_IT_S9_EENS1_14co_spawn_stateIT0_S9_T2_vEEE233_ZN5boost4asio6detail20co_spawn_entry_pointIiNS1_16detached_handlerENS0_15any_io_executorENS1_21awaitable_as_functionIiS4_EEEENS0_9awaitableINS1_28awaitable_thread_entry_pointET1_EEPNS7_IT_S9_EENS1_14co_spawn_stateIT0_S9_T2_vEE.Frame.destroy' referenced in section `.rodata.cst8' of /home/duanyu/projects/asio/obj/x64/Release/test_linka.o: defined in discarded section `.text._ZN5boost4asio6detail20co_spawn_entry_pointEPZNS1_20co_spawn_entry_pointIiNS1_16detached_handlerENS0_15any_io_executorENS1_21awaitable_as_functionIiS4_EEEENS0_9awaitableINS1_28awaitable_thread_entry_pointET1_EEPNS7_IT_S9_EENS1_14co_spawn_stateIT0_S9_T2_vEEE233_ZN5boost4asio6detail20co_spawn_entry_pointIiNS1_16detached_handlerENS0_15any_io_executorENS1_21awaitable_as_functionIiS4_EEEENS0_9awaitableINS1_28awaitable_thread_entry_pointET1_EEPNS7_IT_S9_EENS1_14co_spawn_stateIT0_S9_T2_vEE.Frame.destroy[_ZN5boost4asio6detail20co_spawn_entry_pointIiNS1_16detached_handlerENS0_15any_io_executorENS1_21awaitable_as_functionIiS4_EEEENS0_9awaitableINS1_28awaitable_thread_entry_pointET1_EEPNS7_IT_S9_EENS1_14co_spawn_stateIT0_S9_T2_vEE]' of /home/duanyu/projects/asio/obj/x64/Release/test_linka.o
It seems that during the linking phase, the compiler has performed optimizations and removed some symbols. I tried using O0, which is the optimization level where optimization is not enabled, and the linking works fine.
I used the nm command to view all symbols related to co_spawn in both test_link.o and test_linka.o, and the exported content of the two files is consistent.
==========================================================
Apologies, I forgot to mention my dependency information.
The Boost version is either 1.86.0 or 1.84.0; I have tried both versions.
The os info:
$ cat /etc/os-release
NAME="Alibaba Cloud Linux"
VERSION="3 (Soaring Falcon)"
ID="alinux"
ID_LIKE="rhel fedora centos anolis"
VERSION_ID="3"
PLATFORM_ID="platform:al8"
PRETTY_NAME="Alibaba Cloud Linux 3 (Soaring Falcon)"
ANSI_COLOR="0;31"
HOME_URL="https://www.aliyun.com/"
I tried the script of @sehe, but the same issue persisted after execution; Perhaps it is an issue with the system; I hadn’t considered that before. I will try switching to CentOS to see if it makes a difference.
2
Answers
My new environment is not set up yet, but by reading some materials on "COMDAT section," I found the "-fPIC" compilation option, which solved my problem. Although it is usually used to address the issue of dynamic library sharing, it was indeed useful for me. I don't quite understand it, and any friends who know about it are welcome to give guidance.
I compared the exported symbols of test_link.o compiled with and without the "-fPIC" option regarding co_spawn.
no fPIC
with fPic
It can be observed that the exported symbols for "spawn_entry_point" are missing two lines with the ".str1.x" suffix; I suspect that this might be the source of the issue.
You will probably need to describe your system in way more detail. I’ve created a self-contained version of your code with a simplified build script (commenting the things that didn’t work as given):
Which works fine on my Linux box (replaced
head
with bat for prettier output):Also Live On Coliru
Suggestions
I’d simplify and remove unneeded flags. If you can still reproduce it, please mention exact dependency versions.