Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap TGS bridge requests so they cannot block reboots forever #1825

Closed
wants to merge 4 commits into from
Closed
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion src/DMAPI/tgs/v5/bridge.dm
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@

TGS_DEBUG_LOG("Bridge request start")
// This is an infinite sleep until we get a response
var/export_response = world.Export(bridge_request)
var/export_response = ActuallyPerformBridgeRequest(bridge_request)
TGS_DEBUG_LOG("Bridge request complete")

if(!export_response)
Expand Down Expand Up @@ -107,3 +107,45 @@
return

return bridge_response

#define TGS_BRIDGE_WRAP_RETURNED 1
#define TGS_BRIDGE_WRAP_RESPONSE 2

/// world.Export() can hang forever, so we need to give a timeout window.
/datum/tgs_api/v5/proc/ActuallyPerformBridgeRequest(bridge_request)
var/list/bridge_request_tracker = list(
TGS_BRIDGE_WRAP_RETURNED = FALSE,
TGS_BRIDGE_WRAP_RESPONSE = null
)

var/start_time = world.time
while(bridge_request_tracker[TGS_BRIDGE_WRAP_RETURNED] == FALSE)
AffectedArc07 marked this conversation as resolved.
Show resolved Hide resolved
if(world.time > (start_time + 30 SECONDS)) // A total of 30 seconds worth of bridge attempts are allowed.
TGS_ERROR_LOG("TGS took too long to respond to a bridge request OR byond couldn't reach TGS.")
return null

WrapBridgeRequest(bridge_request, bridge_request_tracker)
var/poll_start_time = world.time
// Every bridge attempt gets an initial 10 seconds to respond.
while(world.time < poll_start_time + 10 SECONDS)
sleep(world.tick_lag)
if(bridge_request_tracker[TGS_BRIDGE_WRAP_RETURNED] == TRUE)
Kapu1178 marked this conversation as resolved.
Show resolved Hide resolved
return bridge_request_tracker[TGS_BRIDGE_WRAP_RESPONSE]

if(bridge_request_tracker[TGS_BRIDGE_WRAP_RETURNED] == TRUE)
Kapu1178 marked this conversation as resolved.
Show resolved Hide resolved
return bridge_request_tracker[TGS_BRIDGE_WRAP_RESPONSE]

/// Async wrapper around a request, we will poll it later.
/datum/tgs_api/v5/proc/WrapBridgeRequest(bridge_request, list/out)
set waitfor = FALSE

var/response = world.Export(bridge_request)
// Another bridge request fork responded already.
if(out[TGS_BRIDGE_WRAP_RETURNED])
return

out[TGS_BRIDGE_WRAP_RESPONSE] = response
out[TGS_BRIDGE_WRAP_RETURNED] = TRUE

#undef TGS_BRIDGE_WRAP_RETURNED
#undef TGS_BRIDGE_WRAP_RESPONSE
Loading