Issue building on Ubuntu/ARM
sptrakesh opened this issue · comments
Hello,
I am trying to build Photon on Ubuntu/ARM combination (noble and gcc13). Compilation fails (version 0.7.3) with the following error:
1.814 /opt/PhotonLibOS/include/photon/net/socket.h:168:36: error: static assertion failed: Endpoint size incorrect
1.814 168 | static_assert(sizeof(EndPoint) == 18, "Endpoint size incorrect");
1.814 | ~~~~~~~~~~~~~~~~~^~~~~
1.815 /opt/PhotonLibOS/include/photon/net/socket.h:168:36: note: the comparison reduces to '(20 == 18)’
struct __attribute__ ((packed)) EndPoint {};
gcc 13 doesn't allow this syntax? Could you try to move __attribute__ ((packed))
after {}
?
Yes, moving the attribute does solve the issue. There are a couple of other issues I needed to make. In particular the one related to the alog error shown here probably needs additional investigation, as GCC says it is deprecated behaviour.
/opt/PhotonLibOS/include/photon/common/alog-functionptr.h: In function 'LogBuffer& __printfp__(LogBuffer&, T)':
/opt/PhotonLibOS/include/photon/common/alog-functionptr.h:29:5: error: there are no arguments to 'free' that depend on a template parameter, so a declaration of 'free' must be available [-fpermissive]
29 | free(name);
| ^~~~
/opt/PhotonLibOS/include/photon/common/alog-functionptr.h:29:5: note: (if you use '-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated)
The diff for changes I needed to make to compile Photon:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ed48b29..d41c9aa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -217,6 +217,10 @@ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0)
# This option is enabled by default after -std=c++17
target_compile_options(photon_obj PRIVATE -faligned-new)
endif()
+if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0)
+ # GCC 13 error: there are no arguments to 'free' that depend on a template parameter, so a declaration of 'free' must be available [-fpermissive]
+ target_compile_options(photon_obj PRIVATE -fpermissive)
+endif()
if (actually_built)
add_dependencies(photon_obj ${actually_built})
diff --git a/common/ring.cpp b/common/ring.cpp
index b87eafb..2ff5eac 100644
--- a/common/ring.cpp
+++ b/common/ring.cpp
@@ -60,7 +60,7 @@ ssize_t RingBuffer::do_read(void *buf, size_t count)
ssize_t RingBuffer::readv(const struct iovec *iov, int iovcnt)
{
ssize_t size = 0;
- scoped_lock lock(m_read_lock);
+ photon::scoped_lock lock(m_read_lock);
for (auto& x: ptr_array(iov, iovcnt))
{
auto ret = do_read(x.iov_base, x.iov_len);
@@ -110,7 +110,7 @@ ssize_t RingBuffer::do_write(const void* buf, size_t count)
ssize_t RingBuffer::writev(const struct iovec *iov, int iovcnt)
{
ssize_t size = 0;
- scoped_lock lock(m_write_lock);
+ photon::scoped_lock lock(m_write_lock);
for (auto& x: ptr_array(iov, iovcnt))
{
auto ret = do_write(x.iov_base, x.iov_len);
diff --git a/net/curl.cpp b/net/curl.cpp
index f2eeb33..9e03925 100644
--- a/net/curl.cpp
+++ b/net/curl.cpp
@@ -19,6 +19,7 @@ limitations under the License.
#include <shared_mutex>
#include <vector>
#include <memory>
+#include <string>
#include <photon/common/alog.h>
#include <photon/common/event-loop.h>
diff --git a/net/socket.h b/net/socket.h
index 75592a6..555197e 100644
--- a/net/socket.h
+++ b/net/socket.h
@@ -42,12 +42,12 @@ LogBuffer& operator << (LogBuffer& log, const sockaddr& addr);
namespace photon {
namespace net {
- struct __attribute__ ((packed)) IPAddr {
+ struct IPAddr {
public:
union {
in6_addr addr = {};
struct { uint16_t _1, _2, _3, _4, _5, _6; uint8_t a, b, c, d; };
- };
+ } __attribute__ ((packed));
// For compatibility, the default constructor is still 0.0.0.0 (IPv4)
IPAddr() {
map_v4(htonl(INADDR_ANY));
@@ -141,11 +141,11 @@ namespace net {
addr._in_addr_field[2] = htonl(0xffff);
addr._in_addr_field[3] = nl;
}
- };
+ } __attribute__ ((packed));
static_assert(sizeof(IPAddr) == 16, "IPAddr size incorrect");
- struct __attribute__ ((packed)) EndPoint {
+ struct EndPoint {
IPAddr addr;
uint16_t port = 0;
EndPoint() = default;
@@ -163,7 +163,7 @@ namespace net {
bool undefined() const {
return addr.undefined() && port == 0;
}
- };
+ } __attribute__ ((packed));
static_assert(sizeof(EndPoint) == 18, "Endpoint size incorrect");
One test fails. Details below:
Test project /opt/PhotonLibOS/build
Start 25: test-rpc-message
1/1 Test #25: test-rpc-message .................***Failed 0.02 sec
2023/12/18 16:30:28|INFO |th=0000AAAAF2A51930|/opt/PhotonLibOS/io/epoll.cpp:289|new_epoll_engine:Init event engine: epoll
2023/12/18 16:30:28|INFO |th=0000AAAAF2A51930|/opt/PhotonLibOS/io/signal.cpp:265|sync_signal_init:signalfd initialized
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from rpc
[ RUN ] rpc.message
2023/12/18 16:30:28|INFO |th=0000AAAAF2A51930|/opt/PhotonLibOS/rpc/rpc.cpp:472|get_socket:Connect to 127.0.0.1:59413
2023/12/18 16:30:28|DEBUG|th=0000FFFFB2E1C700|/opt/PhotonLibOS/rpc/test/test-rpc-message.cpp:44|check_map_order:val-1
2023/12/18 16:30:28|DEBUG|th=0000FFFFB2E1C700|/opt/PhotonLibOS/rpc/test/test-rpc-message.cpp:44|check_map_order:val-2
2023/12/18 16:30:28|DEBUG|th=0000FFFFB2E1C700|/opt/PhotonLibOS/rpc/test/test-rpc-message.cpp:44|check_map_order:val-3
2023/12/18 16:30:28|DEBUG|th=0000AAAAF2A51930|/opt/PhotonLibOS/rpc/test/test-rpc-message.cpp:44|check_map_order:val-5-1
2023/12/18 16:30:28|DEBUG|th=0000AAAAF2A51930|/opt/PhotonLibOS/rpc/test/test-rpc-message.cpp:44|check_map_order:val-5-2
2023/12/18 16:30:28|DEBUG|th=0000AAAAF2A51930|/opt/PhotonLibOS/rpc/test/test-rpc-message.cpp:44|check_map_order:val-5-3
2023/12/18 16:30:28|INFO |th=0000AAAAF2A51930|/opt/PhotonLibOS/rpc/test/test-rpc-message.cpp:216|TestBody:Test finished, shutdown server...
2023/12/18 16:30:28|ERROR|th=0000FFFFB3621280|/opt/PhotonLibOS/rpc/rpc.cpp:254|read_request:Failed to read rpc header 0000AAAAF2A4D3F0[ret=-1]errno=4(Interrupted system call)
[ OK ] rpc.message (3 ms)
[ RUN ] rpc.variable_length_serialization
2023/12/18 16:30:28|DEBUG|th=0000AAAAF2A51930|/opt/PhotonLibOS/rpc/test/test-rpc-message.cpp:238|TestBody:send iov ->
2023/12/18 16:30:28|DEBUG|th=0000AAAAF2A51930|/opt/PhotonLibOS/common/iovector.cpp:338|debug_print:iov sum: 281474211218744, {addr: 0xaaaac22acd80, len: 281474211218720}, {addr: 0xffffd25f8470, len: 24},
/opt/PhotonLibOS/rpc/test/test-rpc-message.cpp:241: Failure
Expected equality of these values:
bytes
Which is: 4096
s_send.iov.sum()
Which is: 281474211218744
[ FAILED ] rpc.variable_length_serialization (0 ms)
[----------] 2 tests from rpc (3 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (3 ms total)
[ PASSED ] 1 test.
[ FAILED ] 1 test, listed below:
[ FAILED ] rpc.variable_length_serialization
1 FAILED TEST
2023/12/18 16:30:28|DEBUG|th=0000FFFFB4E39740|/opt/PhotonLibOS/io/signal.cpp:139|wait_for_signal:wait for signalfd failed because errno=4(Interrupted system call), stop watching
2023/12/18 16:30:28|INFO |th=0000AAAAF2A51930|/opt/PhotonLibOS/io/signal.cpp:301|sync_signal_fini:signalfd finished
2023/12/18 16:30:28|INFO |th=0000AAAAF2A51930|/opt/PhotonLibOS/io/epoll.cpp:75|~EventEngineEPoll:Finish event engine: epoll
0% tests passed, 1 tests failed out of 1
Total Test time (real) = 0.02 sec
The following tests FAILED:
25 - test-rpc-message (Failed)
Errors while running CTest
/opt/PhotonLibOS/include/photon/common/alog-functionptr.h:29:5: error: there are no arguments to 'free' that depend on a template parameter, so a declaration of 'free' must be available [-fpermissive]
try adding #include <stdlib.h>
/opt/PhotonLibOS/rpc/test/test-rpc-message.cpp:241: Failure
I'll take look at this.
{addr: 0xaaaac22acd80, len: 281474211218720}
This length is not correct.
Is the error deterministically reproducible?
If so, can you add a log output as following to see more detail?
@@ -232,6 +232,7 @@ TEST(rpc, variable_length_serialization) {
VariableLengthMessage m_send;
m_send.a = 1;
m_send.b.assign(send_string);
+ LOG_DEBUG(VALUE(m_send.b._ptr), VALUE(m_send.b._len));
photon::rpc::SerializerIOV s_send;
s_send.serialize(m_send);
This is weird. The invalid length looks like the side effect of an uninitialised variable. Adding the log somehow seems to remove that issue. I tried this a few times, without the log statement the test will fail, while with the log statement it will pass.
This sounds like a compiler bug. Can you make another try by replacing the log with an empty inline assembly as follow:
@@ -232,6 +232,7 @@ TEST(rpc, variable_length_serialization) {
VariableLengthMessage m_send;
m_send.a = 1;
m_send.b.assign(send_string);
+ asm volatile ("");
photon::rpc::SerializerIOV s_send;
s_send.serialize(m_send);
This acts like a barrier to (hopefully) prevent some aggressive optimization.
This sounds like a compiler bug. Can you make another try by replacing the log with an empty inline assembly as follow:
@@ -232,6 +232,7 @@ TEST(rpc, variable_length_serialization) { VariableLengthMessage m_send; m_send.a = 1; m_send.b.assign(send_string); + asm volatile (""); photon::rpc::SerializerIOV s_send; s_send.serialize(m_send);This acts like a barrier to (hopefully) prevent some aggressive optimization.
No, does not work. Adding the log still works...
No, does not work. Adding the log still works...
try this:
asm volatile ("" : "+r"(m_send.b._ptr), "+r"(m_send.b._len));
No, does not work. Adding the log still works...
try this: asm volatile ("" : "+r"(m_send.b._ptr), "+r"(m_send.b._len));
Yes, this works.
try this: asm volatile ("" : "+r"(m_send.b._ptr), "+r"(m_send.b._len));
Yes, this works.
So it confirms that the compiler has bugs. This piece of assembly code is actually a noop. It only prevents the optimizer from reordering of load / stores across the line.