Skip to content

Commit e9cd872

Browse files
fix(signalling): do not crash when a forced subscription is declined (#958) (#969)
* fix(signalling): do not crash when a forced subscription is declined sendToStreamer() force-subscribes a player that sends a message while unsubscribed, then forwards the message through non-null assertions on subscribedStreamer. subscribe() can decline - most commonly because maxSubscribers is already reached - and signals that only by leaving subscribedStreamer unset, so the assertions throw a TypeError out of a websocket message handler and bring the whole process down with them, disconnecting every other player. This is easiest to hit at --max_players 1, where the second player to send anything is by definition over the limit. Check the subscription took and disconnect that one player if it did not, which is what the branch above already does when there is no streamer to subscribe to at all. * chore: declare wilbur in the forced-subscribe crash changeset The fix ships to operators as Wilbur, so name it in the changeset rather than letting it land as a bare "updated dependencies" entry. Matches the two most recent Signalling changesets, which both list it alongside the library. --------- (cherry picked from commit c6e78fb) Co-authored-by: marekl11 <55535563+marekl11@users.noreply.github.com>
1 parent 1ada332 commit e9cd872

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@epicgames-ps/lib-pixelstreamingsignalling-ue5.8': patch
3+
'@epicgames-ps/wilbur': patch
4+
---
5+
6+
Stop an unsubscribed player from crashing the signalling server. When a player sends a message without being subscribed, `sendToStreamer` force-subscribes it to the first available streamer and then forwards through `this.subscribedStreamer!`. `subscribe()` can decline — most commonly because `maxSubscribers` is already reached — and reports that only by leaving `subscribedStreamer` unset, so the non-null assertions throw a TypeError out of a websocket message handler and take the process down, disconnecting every other player. It now checks the subscription took, and disconnects just that player if it did not.

Signalling/src/PlayerConnection.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,22 @@ export class PlayerConnection implements IPlayer, LogUtils.IMessageLogger {
142142
} else {
143143
Logger.warn(`Subscribing to ${streamerId}`);
144144
this.subscribe(streamerId);
145+
// subscribe() declines silently, most often because maxSubscribers is reached, and
146+
// says so only by leaving subscribedStreamer unset. Forwarding anyway dereferences
147+
// null, which surfaces as an uncaughtException and exits the process.
148+
if (!this.subscribedStreamer) {
149+
Logger.error(
150+
`Player ${this.playerId} could not be subscribed to ${streamerId}. Disconnecting.`
151+
);
152+
this.disconnect();
153+
return;
154+
}
145155
}
146156
}
147157

148158
message.playerId = this.playerId;
149-
LogUtils.logForward(this, this.subscribedStreamer!, message);
150-
this.subscribedStreamer!.protocol.sendMessage(message);
159+
LogUtils.logForward(this, this.subscribedStreamer, message);
160+
this.subscribedStreamer.protocol.sendMessage(message);
151161
}
152162

153163
private subscribe(streamerId: string) {

0 commit comments

Comments
 (0)