question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

HTTP: WebSocket crash on WsPerformingCheckState leads to "Unexpected onTimeout call in WsCrashedState"

See original GitHub issue

Version: 3.5.1

In some situations our simulations have a few (one or two) users hanging due to a crashed websocket connection. I would expect that the crashed websocket does not lead to some internal timeouts still being triggered and the users hanging indefinitely.

After playing around with a simple simulation and a websocket server implementation in NodeJS I was able to reproduce this when the WebSocket server itself crashes after the connection.

Gatling Scenario:

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
import io.gatling.http.protocol.HttpProtocolBuilder

class DevSim extends Simulation {

  def httpConf: HttpProtocolBuilder = {
    var httpConf = http
      .baseUrl("https://localhost")
      .acceptHeader("application/json, application/hal+json")
      .acceptLanguageHeader("en-US,en;q=0.5")
      .acceptEncodingHeader("gzip, deflate")
      .userAgentHeader("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36")
      .wsBaseUrl("ws://localhost:81")
      .inferHtmlResources()
      .disableWarmUp
    httpConf
  }

  def webSocketName = "testWebSocket"

  def devSim = scenario("WS Test Scenario")
    .exitBlockOnFail(
      exec(ws("Connect").wsName(webSocketName).connect("ws://localhost:81").await(1.second)(ws.checkTextMessage("login").silent))
    )
    .repeat(10) {
      exitBlockOnFail(
      exec(ws("Send Text").wsName(webSocketName).sendText("Hello")
        .await(1.second)(
          ws.checkTextMessage("Check Result").check(regex("Hi, you sent me Hello").exists)
        ))
        .pause(5.second)
      )
    }

  setUp(
    devSim.inject(atOnceUsers(1))
      .protocols(httpConf)
  ).assertions(global.successfulRequests.percent.is(100))
}

WebSocket Server:

var WebSocket = require('ws');

const ws_server = new WebSocket.Server({ port: 81 });
function log(message) {
    console.log(new Date(Date.now()) + " - " + message)
}

ws_server.on('connection', function connection(ws) {
    // important is that the JSON.stringify(ws) call let's the server crash
   // because it is trying to convert a circular structure to JSON
    log("A client connected - " + JSON.stringify(ws));
    ws.on('message', function incoming(message) {
        log("Received " + message);
        ws.send('Hi, you sent me ' + message);
    });
});

ws_server.on('close', function () {
    log("A client closed the connection.");
});

Log output:

5269 [GatlingSystem-akka.actor.default-dispatcher-6] INFO  i.g.core.controller.inject.Injector - Injecting is done
5312 [gatling-1-1] DEBUG io.gatling.http.action.ws.WsConnect - Opening websocket 'testWebSocket': Scenario 'WS Test Scenario', UserId #1
5312 [gatling-1-1] DEBUG io.gatling.http.action.ws.WsConnect - Opening websocket 'testWebSocket': Scenario 'WS Test Scenario', UserId #1
5323 [gatling-1-1] DEBUG i.g.h.a.ws.fsm.WsConnectingState$ - Connecting to ws://localhost:81
5323 [gatling-1-1] DEBUG i.g.h.a.ws.fsm.WsConnectingState$ - Connecting to ws://localhost:81
[...]
9093 [gatling-1-1] DEBUG i.g.c.c.inject.open.OpenWorkload - Start user #1
9121 [gatling-1-1] DEBUG i.n.h.c.h.w.WebSocketClientHandshaker13 - WebSocket version 13 client handshake key: cihrOLzJIaAy/IAw2fAj6A==, expected response: ScedZaO/3T1F5R3OthdFOG9EtdE=
[...]
9161 [gatling-1-1] DEBUG i.gatling.http.action.ws.WsListener - Received response to WebSocket CONNECT: 101 Switching Protocols DefaultHttpHeaders[Upgrade: websocket, Connection: Upgrade, Sec-WebSocket-Accept: ScedZaO/3T1F5R3OthdFOG9EtdE=, content-length: 0]
9161 [gatling-1-1] DEBUG i.gatling.http.action.ws.WsListener - Received response to WebSocket CONNECT: 101 Switching Protocols DefaultHttpHeaders[Upgrade: websocket, Connection: Upgrade, Sec-WebSocket-Accept: ScedZaO/3T1F5R3OthdFOG9EtdE=, content-length: 0]
9165 [gatling-1-1] DEBUG i.g.h.a.ws.fsm.WsConnectingState - Connected, performing checks before proceeding (no onConnected action)
9165 [gatling-1-1] DEBUG i.g.h.a.ws.fsm.WsConnectingState - Connected, performing checks before proceeding (no onConnected action)
9167 [gatling-1-1] DEBUG io.gatling.http.action.ws.fsm.WsFsm - Timeout 61592924 scheduled
9167 [gatling-1-1] DEBUG io.gatling.http.action.ws.fsm.WsFsm - Timeout 61592924 scheduled
9247 [gatling-1-1] DEBUG i.g.h.client.impl.WebSocketHandler - channelInactive
9247 [gatling-1-1] DEBUG i.g.h.client.impl.WebSocketHandler - channelInactive
9250 [gatling-1-1] DEBUG i.g.h.client.impl.WebSocketHandler - Crash
io.gatling.http.client.impl.HttpAppHandler$1: Premature close
9250 [gatling-1-1] DEBUG i.g.h.client.impl.WebSocketHandler - Crash
io.gatling.http.client.impl.HttpAppHandler$1: Premature close
9254 [gatling-1-1] DEBUG i.g.h.a.w.f.WsPerformingCheckState - WebSocket crashed by the server while in WsPerformingCheckState state
io.gatling.http.client.impl.HttpAppHandler$1: Premature close
9254 [gatling-1-1] DEBUG i.g.h.a.w.f.WsPerformingCheckState - WebSocket crashed by the server while in WsPerformingCheckState state
io.gatling.http.client.impl.HttpAppHandler$1: Premature close
10176 [gatling-1-1] DEBUG io.gatling.http.action.ws.fsm.WsFsm - Timeout 61592924 triggered
10176 [gatling-1-1] DEBUG io.gatling.http.action.ws.fsm.WsFsm - Timeout 61592924 triggered
10177 [gatling-1-1] ERROR i.g.h.action.ws.fsm.WsCrashedState - Unexpected onTimeout call in WsCrashedState state
java.lang.IllegalStateException: Unexpected onTimeout call in WsCrashedState state
	at io.gatling.http.action.ws.fsm.WsState.onIllegalState(WsState.scala:80)
	at io.gatling.http.action.ws.fsm.WsState.onTimeout(WsState.scala:77)
	at io.gatling.http.action.ws.fsm.WsFsm.$anonfun$scheduleTimeout$2(WsFsm.scala:56)
	at io.gatling.http.action.ws.fsm.WsFsm.execute(WsFsm.scala:77)
	at io.gatling.http.action.ws.fsm.WsFsm.$anonfun$scheduleTimeout$1(WsFsm.scala:56)
	at io.gatling.http.action.ws.fsm.WsFsm.$anonfun$scheduleTimeout$1$adapted(WsFsm.scala:53)
	at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:96)
	at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:170)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)
10177 [gatling-1-1] ERROR i.g.h.action.ws.fsm.WsCrashedState - Unexpected onTimeout call in WsCrashedState state
java.lang.IllegalStateException: Unexpected onTimeout call in WsCrashedState state
	at io.gatling.http.action.ws.fsm.WsState.onIllegalState(WsState.scala:80)
	at io.gatling.http.action.ws.fsm.WsState.onTimeout(WsState.scala:77)
	at io.gatling.http.action.ws.fsm.WsFsm.$anonfun$scheduleTimeout$2(WsFsm.scala:56)
	at io.gatling.http.action.ws.fsm.WsFsm.execute(WsFsm.scala:77)
	at io.gatling.http.action.ws.fsm.WsFsm.$anonfun$scheduleTimeout$1(WsFsm.scala:56)
	at io.gatling.http.action.ws.fsm.WsFsm.$anonfun$scheduleTimeout$1$adapted(WsFsm.scala:53)
	at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:96)
	at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:170)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)
10179 [gatling-1-1] DEBUG i.g.h.action.ws.fsm.WsCrashedState - WebSocket crashed by the server while in WsCrashedState state
java.lang.IllegalStateException: Unexpected onTimeout call in WsCrashedState state
	at io.gatling.http.action.ws.fsm.WsState.onIllegalState(WsState.scala:80)
	at io.gatling.http.action.ws.fsm.WsState.onTimeout(WsState.scala:77)
	at io.gatling.http.action.ws.fsm.WsFsm.$anonfun$scheduleTimeout$2(WsFsm.scala:56)
	at io.gatling.http.action.ws.fsm.WsFsm.execute(WsFsm.scala:77)
	at io.gatling.http.action.ws.fsm.WsFsm.$anonfun$scheduleTimeout$1(WsFsm.scala:56)
	at io.gatling.http.action.ws.fsm.WsFsm.$anonfun$scheduleTimeout$1$adapted(WsFsm.scala:53)
	at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:96)
	at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:170)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)
10179 [gatling-1-1] DEBUG i.g.h.action.ws.fsm.WsCrashedState - WebSocket crashed by the server while in WsCrashedState state
java.lang.IllegalStateException: Unexpected onTimeout call in WsCrashedState state
	at io.gatling.http.action.ws.fsm.WsState.onIllegalState(WsState.scala:80)
	at io.gatling.http.action.ws.fsm.WsState.onTimeout(WsState.scala:77)
	at io.gatling.http.action.ws.fsm.WsFsm.$anonfun$scheduleTimeout$2(WsFsm.scala:56)
	at io.gatling.http.action.ws.fsm.WsFsm.execute(WsFsm.scala:77)
	at io.gatling.http.action.ws.fsm.WsFsm.$anonfun$scheduleTimeout$1(WsFsm.scala:56)
	at io.gatling.http.action.ws.fsm.WsFsm.$anonfun$scheduleTimeout$1$adapted(WsFsm.scala:53)
	at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:96)
	at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:170)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)

Full log output can be found here

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
slandellecommented, May 26, 2021

Fixed, thanks for reporting again!

1reaction
slandellecommented, Apr 21, 2021

@jklingelAvid Lack of sleep, sorry 😃

Thanks, having a look.

Read more comments on GitHub >

github_iconTop Results From Across the Web

HTTP: WebSocket crash on WsPerformingCheckState leads to ...
HTTP : WebSocket crash on WsPerformingCheckState leads to "Unexpected onTimeout call in WsCrashedState". This issue has been tracked since 2021-04-21.
Read more >
Websocket crash on v4 · Issue #4237 · gatling/gatling - GitHub
[DEBUG] i.g.h.a.w.f.WsPerformingCheckState - WebSocket remotely closed ... WebSocket was already crashed: [DEBUG] i.g.h.a.w.f.WsCrashedState ...
Read more >
Both sides - websockets 10.4 documentation
ConnectionClosedError: sent 1011 (unexpected error) keepalive ping timeout; no close frame received. or if a client crashes with this traceback:.
Read more >
websocket closing connection automatically - Stack Overflow
I have not seen any browsers close WebSocket connections due to inactivity nor have I encountered other WebSocket servers that timeout ...
Read more >
Troubleshooting connection issues | Socket.IO
Problem: the socket is not able to connect​. Possible explanations: You are trying to reach a plain WebSocket server; The server is not ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found