diff --git a/includes/class-wc-background-emailer.php b/includes/class-wc-background-emailer.php index 396f7a4c1ac..c5b9412abe8 100644 --- a/includes/class-wc-background-emailer.php +++ b/includes/class-wc-background-emailer.php @@ -37,7 +37,7 @@ class WC_Background_Emailer extends WP_Background_Process { $this->action = 'wc_emailer'; // Dispatch queue after shutdown. - add_action( 'shutdown', array( $this, 'dispatch_queue' ) ); + add_action( 'shutdown', array( $this, 'dispatch_queue' ), 100 ); parent::__construct(); } @@ -75,11 +75,40 @@ class WC_Background_Emailer extends WP_Background_Process { return false; } + /** + * Finishes replying to the client, but keeps the process running for further (async) code execution. + * + * @see https://core.trac.wordpress.org/ticket/41358 . + */ + protected function close_http_connection() { + // Only 1 PHP process can access a session object at a time, close this so the next request isn't kept waiting. + // @codingStandardsIgnoreStart + if ( session_id() ) { + session_write_close(); + } + // @codingStandardsIgnoreEnd + + wc_set_time_limit( 0 ); + + // fastcgi_finish_request is the cleanest way to send the response and keep the script running, but not every server has it. + if ( is_callable( 'fastcgi_finish_request' ) ) { + fastcgi_finish_request(); + } else { + // Fallback: send headers and flush buffers. + if ( ! headers_sent() ) { + header( 'Connection: close' ); + } + @ob_end_flush(); + flush(); + } + } + /** * Save and run queue. */ public function dispatch_queue() { if ( ! empty( $this->data ) ) { + $this->close_http_connection(); $this->save()->dispatch(); } }