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

dns: refactor QueryWrap lifetime management #26253

Closed
wants to merge 1 commit into from

Conversation

Projects
None yet
4 participants
@addaleax
Copy link
Member

commented Feb 21, 2019

  • Prefer RAII-style management over manual resource management.
  • Prefer env->SetImmediate() over a separate uv_async_t.
  • Perform ares_destroy() before possibly tearing down c-ares state.
  • Verify that the number of active queries is non-negative.
  • Let pending callbacks know when their underlying QueryWrap object
    has been destroyed.

The last item has been a real bug, in that when Workers shut down
during currently running DNS queries, they may run into use-after-free
situations because:

  1. Shutting the Worker down leads to the cleanup code deleting
    the QueryWrap objects first; then
  2. deleting the ChannelWrap object (as it has been created before
    the QueryWraps), whose destructor runs ares_destroy(), which
    in turn invokes all pending query callbacks with ARES_ECANCELLED,
  3. which lead to use-after-free, as the callback tried to access the
    deleted QueryWrap object.

The added test verifies that this is no longer an issue.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
dns: refactor QueryWrap lifetime management
- Prefer RAII-style management over manual resource management.
- Prefer `env->SetImmediate()` over a separate `uv_async_t`.
- Perform `ares_destroy()` before possibly tearing down c-ares state.
- Verify that the number of active queries is non-negative.
- Let pending callbacks know when their underlying `QueryWrap` object
  has been destroyed.

The last item has been a real bug, in that when Workers shut down
during currently running DNS queries, they may run into use-after-free
situations because:

1. Shutting the `Worker` down leads to the cleanup code deleting
   the `QueryWrap` objects first; then
2. deleting the `ChannelWrap` object (as it has been created before
   the `QueryWrap`s), whose destructor runs `ares_destroy()`, which
   in turn invokes all pending query callbacks with `ARES_ECANCELLED`,
3. which lead to use-after-free, as the callback tried to access the
   deleted `QueryWrap` object.

The added test verifies that this is no longer an issue.

@addaleax addaleax added the dns label Feb 21, 2019

@addaleax addaleax added worker and removed cares labels Feb 21, 2019

@addaleax

This comment has been minimized.

Copy link
Member Author

commented Feb 28, 2019

Maybe one of @XadillaX @gireeshpunathil @joyeecheung @cjihrig could review this?

@addaleax

This comment has been minimized.

Copy link
Member Author

commented Mar 1, 2019

@jasnell

jasnell approved these changes Mar 1, 2019

@addaleax

This comment has been minimized.

Copy link
Member Author

commented Mar 1, 2019

@addaleax

This comment has been minimized.

Copy link
Member Author

commented Mar 1, 2019

Landed in 018e95a

@addaleax addaleax closed this Mar 1, 2019

@addaleax addaleax deleted the addaleax:cares-terminate branch Mar 1, 2019

addaleax added a commit that referenced this pull request Mar 1, 2019

dns: refactor QueryWrap lifetime management
- Prefer RAII-style management over manual resource management.
- Prefer `env->SetImmediate()` over a separate `uv_async_t`.
- Perform `ares_destroy()` before possibly tearing down c-ares state.
- Verify that the number of active queries is non-negative.
- Let pending callbacks know when their underlying `QueryWrap` object
  has been destroyed.

The last item has been a real bug, in that when Workers shut down
during currently running DNS queries, they may run into use-after-free
situations because:

1. Shutting the `Worker` down leads to the cleanup code deleting
   the `QueryWrap` objects first; then
2. deleting the `ChannelWrap` object (as it has been created before
   the `QueryWrap`s), whose destructor runs `ares_destroy()`, which
   in turn invokes all pending query callbacks with `ARES_ECANCELLED`,
3. which lead to use-after-free, as the callback tried to access the
   deleted `QueryWrap` object.

The added test verifies that this is no longer an issue.

PR-URL: #26253
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>

addaleax added a commit that referenced this pull request Mar 1, 2019

dns: refactor QueryWrap lifetime management
- Prefer RAII-style management over manual resource management.
- Prefer `env->SetImmediate()` over a separate `uv_async_t`.
- Perform `ares_destroy()` before possibly tearing down c-ares state.
- Verify that the number of active queries is non-negative.
- Let pending callbacks know when their underlying `QueryWrap` object
  has been destroyed.

The last item has been a real bug, in that when Workers shut down
during currently running DNS queries, they may run into use-after-free
situations because:

1. Shutting the `Worker` down leads to the cleanup code deleting
   the `QueryWrap` objects first; then
2. deleting the `ChannelWrap` object (as it has been created before
   the `QueryWrap`s), whose destructor runs `ares_destroy()`, which
   in turn invokes all pending query callbacks with `ARES_ECANCELLED`,
3. which lead to use-after-free, as the callback tried to access the
   deleted `QueryWrap` object.

The added test verifies that this is no longer an issue.

PR-URL: #26253
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>

@BridgeAR BridgeAR referenced this pull request Mar 4, 2019

Merged

v11.11.0 proposal #26322

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.