WordPress.org

Make WordPress Core

Opened 5 years ago

Last modified 3 years ago

#8923 reopened defect (bug)

cron timeout is too short

Reported by: hailin Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version:
Component: Cron API Keywords: needs-patch reporter-feedback
Focuses: Cc:

Description

Many users have reported that 2.7 cron sometimes fails to publish future post.
And it is further reported that it depends on the number of jobs on the cron queue - when the queue is too long, it will miss some.

I believe this is because we set the timeout value too short:

wp_remote_post($cron_url, array('timeout' => 0.01, 'blocking' => false));

When making a request to wp-cron.php, it won't return until all cron jobs are executed. And 0.01 is just too short time span. It doesn't hurt to give it sufficent time, such as 10 minutes. It will return as long as the mature crons are fired up and executed (in most cases, it's going to be at most a few seconds ).

Attachments (1)

8923_cron.diff (517 bytes) - added by hailin 5 years ago.
patch

Download all attachments as: .zip

Change History (27)

hailin5 years ago

patch

comment:2 ryan5 years ago

Such a long timeout would defy the point of spawning cron.

comment:4 hailin5 years ago

In the old code, where we used

fsockopen( $partshost?, $_SERVERSERVER_PORT?, $errno, $errstr, 0.01)
fputs( $argyle, "GET {$partspath?}?check=" . wp_hash('187425'). ...)
0.01 only controls the the fsocketopen TCP handshake phase, it was saying
"the timeout for 3-way TCP handshake is only 0.01 sec", which is enough since the host is local. Then we shovel GET into the pipe, and return. All good.

The new code changed the semantics:

wp_remote_post($cron_url, array('timeout' => 0.01, 'blocking' => false));

Here the timeout is application layer timeout, meaning "If HTTP doesn't get anything back in 0.01 sec, let's close the connection". When there are many cron jobs in the queue, it's going to take longer time to fire them up. And after 0.01 sec, the client closes the connection, either by sending RST, or other means. This interrupts cron jobs despite we have ignore_user_abort(true); at the beginning of wp-cron.php

So if we want to retain the "close without waiting" intent, it appears only the old code achieves it. Otherwise, if we stick to wp_remote_post, 0.01 is going to cause issues.

comment:5 jacobsantos5 years ago

It appears that not all of the transports are working as they should. Probably should be increased to a second, since not all of the transports support floats and something less than 1 second.

comment:6 follow-up: hailin5 years ago

wp_remote_post is going to wait until all the cron jobs are done, or timeout at the proposed 1 sec. 1 sec should be enough for most publish_future_posts, but pings can take longer time...

comment:7 in reply to: ↑ 6 westi5 years ago

Replying to hailin:

wp_remote_post is going to wait until all the cron jobs are done, or timeout at the proposed 1 sec. 1 sec should be enough for most publish_future_posts, but pings can take longer time...

As Ryan said the whole point of the cron is to go async.

If we have to block the request that spawns it by 1 second to ensure it works we might as well do it in-line :-(

I think we need to step back and look at how we can achieve the desired goal easily in PHP4/5/6 rather than just keep tinkering with the timeouts.

comment:8 thehalogod5 years ago

I changed the code as suggested from 0.01 to 10*60 and the post still did not post as scheduled. It just said "missed timeline" (or schedule) I can't remember the exact phrase.

Any other ideas on why scheduling posts doesn't seem to work?

comment:9 DD325 years ago

Any other ideas on why scheduling posts doesn't seem to work?

Because your WordPress cannot make a request to itself.

Generally this is unique solution to the server, While one way might work for one person, It might not work for another.. The method in WordPress Core tends to work for -most- people.

I'm not sure of all the options, You might be best looking back at cron-related tickets and support forum posts (That'd be the best place for this discussion really..)

comment:10 follow-up: Otto425 years ago

  • Milestone 2.8 deleted
  • Resolution set to invalid
  • Status changed from new to closed

The timeout does not matter. This is just sending the request to cause the wp-cron to execute on the server. We don't care what the results are, it's just making it start running.

Marking as invalid, because raising that timeout does nothing.

comment:11 hailin5 years ago

  • Resolution invalid deleted
  • Status changed from closed to reopened

I still think the reasoning stated in the ticket was correct.

In fact, I changed the timeout to 2 seconds and tested it at WordPress.com,
it's been very smooth and didn't see missed future post issues for over a month.

comment:12 DD325 years ago

  • Milestone set to Unassigned

In fact, I changed the timeout to 2 seconds and tested it at WordPress.com, it's been very smooth and didn't see missed future post issues for over a month.

Which transport does WordPress.com use?

Remember that the Timeout here is only used for the connection timeout, Not for the actual waiting of the loading of the page.

There was an issue with the cURL transport where a 0.01 timeout would cause it to never create the connection, A fix was put in for that: http://core.trac.wordpress.org/browser/trunk/wp-includes/http.php#L1191

comment:13 hailin5 years ago

WordPress.com uses the same transport implemented in wp-includes/http.php
Even if 0.01 is the cURL transport timeout, I don't see any harm to increase it to 1 or 2 sec, because in most cases it's going to take only a few miliseconds.

Since cron is fired up once only, so in the worst case, letting one page view pay the 1 sec penalty, while improving the reliability, doesn't sound too bad.

comment:14 DD325 years ago

WordPress.com uses the same transport implemented in wp-includes/http.php

Thats the thing, HTTP has 5 different transports defined :) and only a few were affected, Was just curious as to which had the problem.

And you're right, a slight delay shouldnt be a problem if it only happens once in awhile, but, The problem is, That on some setups, cron ends up being fired on every page load because its having cron-firing-issues..

eitherway, I do support changing it.. and maybe a define-override or filter(Which is already present i think)

comment:15 Otto425 years ago

I disagree. If there's a problem with a specific transport not firing the request off because the timeout is too short, then the transport itself needs to be fixed. Upping the timeout is only a bandaid solution, because the whole point of this request is that we don't care what the response is. Ideally, the timeout would be zero or nonexistent, because we want this function to a) fire the request off and b) return. Thus completely ignoring the response and having no delay in waiting for it.

If increasing this timeout "fixes" anything, then we need to determine what transport is being used on that system and then why that transport is not firing the http request off when the timeout is so low.

comment:16 ryan5 years ago

wpcom uses curl. The curl transport bumps the 0.01 timeout to 1 since it doesn't handle floats. As far as I know that was working fine.

comment:17 in reply to: ↑ 10 Denis-de-Bernardy5 years ago

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

Replying to Otto42:

The timeout does not matter. This is just sending the request to cause the wp-cron to execute on the server. We don't care what the results are, it's just making it start running.

Marking as invalid, because raising that timeout does nothing.

+1 to that. If it's the transport, the transport should be fixed (as was done with curl).

comment:18 Denis-de-Bernardy5 years ago

  • Milestone Unassigned deleted

comment:19 follow-up: bueltge5 years ago

  • Milestone set to 2.8.1
  • Resolution invalid deleted
  • Status changed from closed to reopened

Many people have also this problem after update to 2.8:
wp_remote_post( $cron_url, array('timeout' => 0.01

comment:20 Denis-de-Bernardy5 years ago

  • Component changed from General to Cron

comment:21 in reply to: ↑ 19 westi5 years ago

  • Keywords reporter-feedback added

Replying to bueltge:

Many people have also this problem after update to 2.8:
wp_remote_post( $cron_url, array('timeout' => 0.01

Can we have more information here please.

What problem?
What fix are you suggesting?

comment:22 bueltge5 years ago

The actual fix change only the value timeout to 1. In all blogs with this problems works the ping then great. Other people have deactivate fopen on webspace and it is not possible to use the ping-function. Maybe it is possible, the problem installs have a small webspace, small memory?

comment:23 scribu4 years ago

  • Keywords needs-patch added; reporter-feedback removed

comment:24 westi4 years ago

  • Keywords reporter-feedback added
  • Milestone changed from 2.9 to Future Release

Moving to Future until we have a clearly defined test case.

  • What Transport fails with a timeout of 0.01

comment:25 techecatocom4 years ago

  • Cc techecatocom added
Note: See TracTickets for help on using tickets.