Make WordPress Core

Opened 3 years ago

Closed 3 years ago

Last modified 8 months ago

#57475 closed defect (bug) (worksforme)

wp_schedule_event function causes "Headers already sent" error

Reported by: onetarek's profile onetarek Owned by:
Milestone: Priority: normal
Severity: normal Version: 6.1.1
Component: Cron API Keywords: has-test-info
Focuses: Cc:

Description

I need to start the PHP session for my plugin. On plugin activation, I am getting PHP Warning.

PHP Warning:  session_start(): Cannot start session when headers already sent in..

On register_activation_hook I am using wp_schedule_event() to register my custom event hook. If I remove wp_schedule_event() I don't see the PHP Warning. So we can say that the wp_schedule_event function prints something that causes the Warning.

To test this issue use my simple plugin code below.

<?php
/**
 * Plugin Name: Test plugin
 * Description: Just a Test plugin
 * Plugin URI: http://onetarek.com
 * Author: oneTarek
 * Author URI: http://onetarek.com
 * Version: 1.0.0
 */


function test_activation() {
        wp_schedule_event( time(), 'daily', 'test_daily_event_hook' );
}

function test_deactivation() {
        wp_clear_scheduled_hook( 'test_daily_event_hook' );
}

register_activation_hook( __FILE__, 'test_activation' ); 

register_deactivation_hook( __FILE__, 'test_deactivation' );

if( session_id() == "" ){ session_start(); }

Install this plugin code. Activate and check debug log. Try activating and deactivating this plugin multiple times if you don't see any Warning.

Attachments (1)

test-plugin.zip (1.1 KB) - added by onetarek 3 years ago.
A very simple plugin to test the issue

Download all attachments as: .zip

Change History (6)

@onetarek
3 years ago

A very simple plugin to test the issue

#1 @onetarek
3 years ago

My site info

WP Version: 6.1.1
PHP version: 7.3.5 (Supports 64bit values)
Web server: Apache/2.4.43 (Unix)
Server architecture: Darwin 17.7.0 x86_64

#2 follow-up: @peterwilsoncc
3 years ago

The warnings in your logs are occurring when the cron job test_daily_event_hook runs, they're not running due to the call to wp_schedule_event().

Calls to wp-cron.php send the headers early in the request. The unconditional call to start the session in your plugin will then attempt to start a session on the wp-cron.php request.

[16-Jan-2023 21:36:55 UTC] PHP Stack trace:
[16-Jan-2023 21:36:55 UTC] PHP   1. {main}() /vagrant/wordpress-develop/src/wp-cron.php:0
[16-Jan-2023 21:36:55 UTC] PHP   2. require_once() /vagrant/wordpress-develop/src/wp-cron.php:46
[16-Jan-2023 21:36:55 UTC] PHP   3. require_once() /vagrant/wordpress-develop/src/wp-load.php:50
[16-Jan-2023 21:36:55 UTC] PHP   4. include() /vagrant/wordpress-develop/src/wp-config.php:9
[16-Jan-2023 21:36:55 UTC] PHP   5. require_once() /vagrant/wp-config.php:147
[16-Jan-2023 21:36:55 UTC] PHP   6. include_once() /vagrant/wordpress-develop/src/wp-settings.php:447
[16-Jan-2023 21:36:55 UTC] PHP   7. session_start() /vagrant/content/plugins/cron-test-plugin/plugin.php:24

WP-cron doesn't support headers or sessions as it can be run either within the browser or via the CLI. I suggest you wrap the call to session_start() in a conditional to ensure it only runs in browser requests.

#3 in reply to: ↑ 2 @onetarek
3 years ago

  • Resolution set to invalid
  • Status changed from new to closed

Replying to peterwilsoncc:

The warnings in your logs are occurring when the cron job test_daily_event_hook runs, they're not running due to the call to wp_schedule_event().

Calls to wp-cron.php send the headers early in the request. The unconditional call to start the session in your plugin will then attempt to start a session on the wp-cron.php request.

[16-Jan-2023 21:36:55 UTC] PHP Stack trace:
[16-Jan-2023 21:36:55 UTC] PHP   1. {main}() /vagrant/wordpress-develop/src/wp-cron.php:0
[16-Jan-2023 21:36:55 UTC] PHP   2. require_once() /vagrant/wordpress-develop/src/wp-cron.php:46
[16-Jan-2023 21:36:55 UTC] PHP   3. require_once() /vagrant/wordpress-develop/src/wp-load.php:50
[16-Jan-2023 21:36:55 UTC] PHP   4. include() /vagrant/wordpress-develop/src/wp-config.php:9
[16-Jan-2023 21:36:55 UTC] PHP   5. require_once() /vagrant/wp-config.php:147
[16-Jan-2023 21:36:55 UTC] PHP   6. include_once() /vagrant/wordpress-develop/src/wp-settings.php:447
[16-Jan-2023 21:36:55 UTC] PHP   7. session_start() /vagrant/content/plugins/cron-test-plugin/plugin.php:24

WP-cron doesn't support headers or sessions as it can be run either within the browser or via the CLI. I suggest you wrap the call to session_start() in a conditional to ensure it only runs in browser requests.

@peterwilsoncc You are right. The header is being sent from wp-cron.php. I put my code in a condition.

<?php
if( "" == session_id() && !defined( 'DOING_CRON' ) && !isset( $_GET['doing_wp_cron'] ) ){ 
    session_start(); 
}

Now there is no warning.

#4 @peterwilsoncc
3 years ago

  • Milestone Awaiting Review deleted
  • Resolution changed from invalid to worksforme

Thanks for following up, I appreciate the confirmation I wasn't missing an edge case.

I'll close this issue off as worksforme as it's expected behavior for wp-cron to send headers early.

You might need to change a few other things to do with sessions in your plugin but the best place to get assistance for such things is in the Developing with WordPress forum, the folks who hang around there are much better placed to assist.

#5 @wordpressdotorg
8 months ago

  • Keywords has-test-info added; has-testing-info removed
Note: See TracTickets for help on using tickets.