Skip to content

Handle aborted connection#95

Merged
dunglas merged 8 commits into
mainfrom
handle-connection-aborts
Nov 9, 2022
Merged

Handle aborted connection#95
dunglas merged 8 commits into
mainfrom
handle-connection-aborts

Conversation

@withinboredom

Copy link
Copy Markdown
Member

This PR to #90 handles detecting a closed connection and setting the connection state to aborted both during a flush and during a write to output.

Since we were not previously setting the connection state to aborted, this is a breaking change in that by default, PHP stops working once the connection is aborted unless the user calls ignore_user_abort(true); or the ignore_user_abort setting in php.ini.

@withinboredom withinboredom requested a review from dunglas November 8, 2022 14:32
@withinboredom withinboredom force-pushed the handle-connection-aborts branch from f0e95bd to 292545f Compare November 8, 2022 15:40
Comment thread frankenphp.c Outdated
Comment thread frankenphp.c Outdated

size_t wrote = go_ub_write(ctx->current_request ? ctx->current_request : ctx->main_request, (char *) str, str_length, &failed);

if(failed) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
if(failed) {
if (failed) {

(we need to check and fix the CS in the CI btw)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Is there a C-style checker? I'll admit I only recently noticed the space between if & (.

Comment thread frankenphp.go Outdated
Comment thread frankenphp.go Outdated
@withinboredom

Copy link
Copy Markdown
Member Author

Things to test when compared to fastcgi/apache:

  1. fastcgi_finish_request() should return the correct connection status.
  2. fastcgi_finish_request() shouldn't kill processing because the connection is done.
  3. disconnecting before flush.
  4. disconnecting during output.

Due to the very nature of networks, I expect several race conditions need to be accounted for in unit tests (i.e., we can't detect a socket is closed until we write to it and get a reply that it is closed.)

@withinboredom withinboredom force-pushed the handle-connection-aborts branch from 1eb124b to 3e93e6e Compare November 8, 2022 20:44
@dunglas dunglas force-pushed the feat/implement-flush branch from cd4974e to c43dd38 Compare November 8, 2022 23:55
Base automatically changed from feat/implement-flush to main November 8, 2022 23:56
@withinboredom withinboredom force-pushed the handle-connection-aborts branch from 81c7339 to 7eb3e8d Compare November 9, 2022 10:21
Comment thread frankenphp.go
return true
}

flusher.Flush()

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Since Flush() on a closed connection seems to be a noop, I'm inclined to remove the previous if-statement and just return the result of clientHasClosed(). What are your thoughts on that?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's definitely a micro-optim, but doing this in this order prevents a useless call to Flush() event if it's a noop. I don't have a strong opinion on this TBH.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

True. I don't have strong feelings either, so I'll leave as-is. My optimization thought was mostly to reduce the branching, but it's probably better to leave that sort of optimization for a compiler and just describe what is correct.

@dunglas dunglas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Do you think we can prevent the sleep() in the tests?

@withinboredom

withinboredom commented Nov 9, 2022

Copy link
Copy Markdown
Member Author

Do you think we can prevent the sleep() in the tests?

I've been mulling it over. It appears that it all resolves in less than a single millisecond, even on the GitHub runners, so if it becomes an issue, we bump it up to a couple of ms and/or commit upstream to zaptest to get some kind of channel on the log output so we can block until logs are output. There is certainly a race condition here, but I can't think of any way to currently get around it, though I'm open to ideas.

@dunglas dunglas merged commit 3abda4f into main Nov 9, 2022
@dunglas

dunglas commented Nov 9, 2022

Copy link
Copy Markdown
Member

Thank you!

@dunglas dunglas deleted the handle-connection-aborts branch November 9, 2022 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants