Skip to content

Conversation

bneradt
Copy link
Contributor

@bneradt bneradt commented Oct 14, 2025

From a recent instrumented core taking traffic in production:

(gdb) p write_state.vio
$22 = {
  cont = 0x0,
  cont_handler_name = 0x9046f2 "&HttpTunnel::main_handler",
  nbytes = 9223372036854775807,
  ndone = 0,
  op = 2,
  _disabled = false,
  buffer = {
    mbuf = 0x0,
    entry = 0x0
  },
  vc_server = 0x7faa48983920,
  mutex = {
    m_ptr = 0x7fa7bfa24a00
  }
}

Notice that:

  • cont is nullptr
  • nbytes is 9223372036854775807 (INT64_MAX)

These are the default value of do_io_write when no values are passed to it. This doesn't happen in a lot of places, but it does currently in tunnel_handler_100_continue_ua:

       c->vc->do_io_write();

This changes the call to the following more typical way of canceling a vc write operation:

  c->vc->do_io_write(nullptr, 0, nullptr);

This way when a PluginVC::process_timeout event is processed, the ntodo will be 0 and thus the non-existent handler will not be called (see PluginVC.cc):

    } else if (write_state.vio.op == VIO::WRITE && !write_state.shutdown && write_state.vio.ntodo() > 0) {

From a recent instrumented core taking traffic in production:

```
(gdb) p write_state.vio
$22 = {
  cont = 0x0,
  cont_handler_name = 0x9046f2 "&HttpTunnel::main_handler",
  nbytes = 9223372036854775807,
  ndone = 0,
  op = 2,
  _disabled = false,
  buffer = {
    mbuf = 0x0,
    entry = 0x0
  },
  vc_server = 0x7faa48983920,
  mutex = {
    m_ptr = 0x7fa7bfa24a00
  }
}
```

Notice that:

* cont is nullptr
* nbytes is 9223372036854775807 (INT64_MAX)

These are the default value of do_io_write when no values are passed to
it. This doesn't happen in a lot of places, but it does currently in
tunnel_handler_100_continue_ua:

```cpp
       c->vc->do_io_write();
```

This changes the call to the following more typical way of canceling a
vc write operation:

```cpp
  c->vc->do_io_write(nullptr, 0, nullptr);
```

This way when a PluginVC::process_timeout event is processed, the ntodo
will be 0 and thus the non-existent handler will not be called (see
PluginVC.cc):

```cpp
    } else if (write_state.vio.op == VIO::WRITE && !write_state.shutdown && write_state.vio.ntodo() > 0) {
```
@bneradt bneradt added this to the 10.2.0 milestone Oct 14, 2025
@bneradt bneradt self-assigned this Oct 14, 2025
@bneradt bneradt added the Crash label Oct 14, 2025
@bneradt bneradt marked this pull request as ready for review October 16, 2025 18:37
@bryancall bryancall requested a review from shinrich October 20, 2025 22:15
// Disable any write operation in case there are timeout events.
if (c->vc != nullptr) {
c->vc->do_io_write();
c->vc->do_io_write(nullptr, 0, nullptr);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to pass in "this" as the first argument. I've had problems before with state machines getting lost because a terminal event is delivered to a VIO with no continuation to deliver the terminal event to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants