2121
2222#include < quill/Quill.h>
2323
24+ #include < array>
2425#include < chrono>
26+ #include < poll.h>
27+ #include < sys/eventfd.h>
2528#include < sys/socket.h>
2629#include < sys/un.h>
2730#include < thread>
3033struct monad_statesync_server_network
3134{
3235 int fd;
36+ int shutdown_eventfd;
3337 monad::byte_string obuf;
3438 std::string path;
3539
@@ -42,19 +46,50 @@ struct monad_statesync_server_network
4246 memset (&addr, 0 , sizeof (addr));
4347 addr.sun_family = AF_UNIX;
4448 strncpy (addr.sun_path , path.c_str (), sizeof (addr.sun_path ) - 1 );
49+
4550 while (::connect (fd, (sockaddr *)&addr, sizeof (addr)) != 0 ) {
46- std::this_thread::sleep_for (std::chrono::milliseconds (1 ));
51+ // Check if shutdown was requested before sleeping
52+ std::array<pollfd, 1 > pfds{};
53+ pfds[0 ].fd = shutdown_eventfd;
54+ pfds[0 ].events = POLLIN;
55+
56+ // Poll with short timeout to check for shutdown signal
57+ int const poll_ret = poll (pfds.data (), pfds.size (), 1 );
58+
59+ if (poll_ret > 0 && (pfds[0 ].revents & POLLIN)) {
60+ // Shutdown requested, abort connection attempt
61+ LOG_WARNING (" Connect aborted due to shutdown request" );
62+ return ;
63+ }
64+ }
65+ }
66+
67+ void signal_shutdown ()
68+ {
69+ uint64_t const val = 1 ;
70+ ssize_t const res = write (shutdown_eventfd, &val, sizeof (val));
71+ if (res != sizeof (val)) {
72+ LOG_WARNING (
73+ " Failed to signal shutdown eventfd: {}" , strerror (errno));
4774 }
4875 }
4976
5077 monad_statesync_server_network (char const *const path)
5178 : path{path}
5279 {
80+ shutdown_eventfd = eventfd (0 , EFD_CLOEXEC | EFD_NONBLOCK);
81+ MONAD_ASSERT_PRINTF (
82+ shutdown_eventfd >= 0 ,
83+ " failed to create eventfd: %s" ,
84+ strerror (errno));
5385 connect ();
5486 }
5587
5688 ~monad_statesync_server_network ()
5789 {
90+ if (shutdown_eventfd >= 0 ) {
91+ close (shutdown_eventfd);
92+ }
5893 if (fd >= 0 ) {
5994 close (fd);
6095 }
@@ -92,33 +127,76 @@ namespace
92127 }
93128}
94129
95- ssize_t statesync_server_recv (
130+ inline ssize_t statesync_server_recv (
96131 monad_statesync_server_network *const net, unsigned char *buf, size_t n)
97132{
98- while (true ) {
99- ssize_t ret = recv (net->fd , buf, n, MSG_DONTWAIT);
100- if (ret == 0 ||
101- (ret < 0 && (errno == ECONNRESET || errno == ENOTCONN))) {
102- LOG_WARNING (" connection closed, reconnecting" );
133+ size_t total_received = 0 ;
134+
135+ while (total_received < n) {
136+ std::array<pollfd, 2 > pfds{};
137+ pfds[0 ].fd = net->fd ;
138+ pfds[0 ].events = POLLIN;
139+
140+ pfds[1 ].fd = net->shutdown_eventfd ;
141+ pfds[1 ].events = POLLIN;
142+
143+ int const poll_ret = poll (pfds.data (), pfds.size (), -1 );
144+
145+ if (poll_ret < 0 ) {
146+ if (errno == EINTR) {
147+ continue ;
148+ }
149+ LOG_ERROR (" poll error: {}" , strerror (errno));
150+ return -1 ;
151+ }
152+
153+ if (pfds[1 ].revents & POLLIN) {
154+ return -1 ;
155+ }
156+
157+ if (pfds[0 ].revents & (POLLERR | POLLHUP | POLLNVAL)) {
158+ LOG_WARNING (" socket error event, reconnecting" );
103159 if (close (net->fd ) < 0 ) {
104160 LOG_ERROR (" failed to close socket: {}" , strerror (errno));
105161 }
106162 net->fd = -1 ;
107163 net->connect ();
108- }
109- else if (
110- ret < 0 &&
111- (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)) {
112- LOG_ERROR (" recv error: {}" , strerror (errno));
113164 return -1 ;
114165 }
115- else {
116- return ret;
166+
167+ if (pfds[0 ].revents & POLLIN) {
168+ ssize_t const ret = recv (
169+ net->fd ,
170+ buf + total_received,
171+ n - total_received,
172+ MSG_DONTWAIT);
173+
174+ if (ret == 0 ||
175+ (ret < 0 && (errno == ECONNRESET || errno == ENOTCONN))) {
176+ LOG_WARNING (" connection closed, reconnecting" );
177+ if (close (net->fd ) < 0 ) {
178+ LOG_ERROR (" failed to close socket: {}" , strerror (errno));
179+ }
180+ net->fd = -1 ;
181+ net->connect ();
182+ return -1 ;
183+ }
184+ else if (
185+ ret < 0 &&
186+ (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)) {
187+ LOG_ERROR (" recv error: {}" , strerror (errno));
188+ return -1 ;
189+ }
190+ else if (ret > 0 ) {
191+ total_received += static_cast <size_t >(ret);
192+ }
117193 }
118194 }
195+
196+ return static_cast <ssize_t >(n);
119197}
120198
121- void statesync_server_send_upsert (
199+ inline void statesync_server_send_upsert (
122200 monad_statesync_server_network *const net, monad_sync_type const type,
123201 unsigned char const *const v1, uint64_t const size1,
124202 unsigned char const *const v2, uint64_t const size2)
@@ -152,15 +230,15 @@ void statesync_server_send_upsert(
152230 LOG_DEBUG (
153231 " sending upsert type={} {} ns={}" ,
154232 std::to_underlying (type),
155- fmt ::format (
233+ fmtquill ::format (
156234 " v1=0x{:02x} v2=0x{:02x}" ,
157- fmt ::join (std::as_bytes (std::span (v1, size1)), " " ),
158- fmt ::join (std::as_bytes (std::span (v2, size2)), " " )),
235+ fmtquill ::join (std::as_bytes (std::span (v1, size1)), " " ),
236+ fmtquill ::join (std::as_bytes (std::span (v2, size2)), " " )),
159237 std::chrono::duration_cast<std::chrono::nanoseconds>(
160238 std::chrono::steady_clock::now () - start));
161239}
162240
163- void statesync_server_send_done (
241+ inline void statesync_server_send_done (
164242 monad_statesync_server_network *const net, monad_sync_done const msg)
165243{
166244 [[maybe_unused]] auto const start = std::chrono::steady_clock::now ();
0 commit comments