Skip to content

Commit

Permalink
feat: zombie connection check
Browse files Browse the repository at this point in the history
This commit adds the check that verifies if the connection is dead, AKA zombie. Without this, once internet was unavailable for a certain time, Discord would stop responding to the heartbeats and wouldn't send any events, causing to the bot be offline, while the process would be still alive.
  • Loading branch information
ThePedroo committed Mar 21, 2024
1 parent 25aceab commit bc83587
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 0 deletions.
5 changes: 5 additions & 0 deletions include/discord-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,11 @@ struct discord_gateway {
* @note obtained at `HELLO`
*/
int64_t hbeat_interval;
/**
* boolean that indicates if the last heartbeat was answered
* @note used to detect zombie connections
*/
bool hbeat_acknowledged;
/**
* Gateway's concept of "now"
* @note updated at discord_gateway_perform()
Expand Down
4 changes: 4 additions & 0 deletions src/discord-gateway.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ _discord_on_heartbeat_ack(struct discord_gateway *gw)
/* get request / response interval in milliseconds */
pthread_rwlock_wrlock(&gw->timer->rwlock);
gw->timer->ping_ms = (int)(gw->timer->now - gw->timer->hbeat_last);
gw->timer->hbeat_acknowledged = true;
pthread_rwlock_unlock(&gw->timer->rwlock);

logconf_trace(&gw->conf, "PING: %d ms", gw->timer->ping_ms);
Expand Down Expand Up @@ -551,6 +552,9 @@ discord_gateway_init(struct discord_gateway *gw,
ASSERT_S(!pthread_rwlock_init(&gw->timer->rwlock, NULL),
"Couldn't initialize Gateway's rwlock");

/* mark true to not get reconnected each reconnect */
gw->timer->hbeat_acknowledged = true;

/* client connection status */
gw->session = calloc(1, sizeof *gw->session);
gw->session->retry.enable = true;
Expand Down
12 changes: 12 additions & 0 deletions src/discord-gateway_dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,16 @@ discord_gateway_send_heartbeat(struct discord_gateway *gw, int seq)
jsonb_object_pop(&b, buf, sizeof(buf));
}

if (!gw->timer->hbeat_acknowledged) {
logconf_warn(&gw->conf, "Heartbeat ACK not received, marked as zombie");

gw->timer->hbeat_acknowledged = true;

discord_gateway_reconnect(gw, false);

return;
}

if (ws_send_text(gw->ws, &info, buf, b.pos)) {
io_poller_curlm_enable_perform(CLIENT(gw, gw)->io_poller, gw->mhandle);
logconf_info(
Expand All @@ -273,6 +283,8 @@ discord_gateway_send_heartbeat(struct discord_gateway *gw, int seq)
ANSI_FG_BRIGHT_GREEN) " HEARTBEAT (%d bytes) [@@@_%zu_@@@]",
b.pos, info.loginfo.counter + 1);

gw->timer->hbeat_acknowledged = false;

/* update heartbeat timestamp */
gw->timer->hbeat_last = gw->timer->now;
if (!gw->timer->hbeat_timer)
Expand Down

0 comments on commit bc83587

Please sign in to comment.