Index: wp-includes/functions.php
===================================================================
--- wp-includes/functions.php	(revision 3630)
+++ wp-includes/functions.php	(working copy)
@@ -2420,72 +2420,6 @@
 	return $wpdb->num_queries;
 }
 
-function wp_schedule_event($timestamp, $recurrence, $hook) {
-	$args = array_slice(func_get_args(), 3);
-	$crons = get_option('cron');
-	$crons[$timestamp][$hook] = array('recur' => $recurrence, 'args' => $args);
-	ksort($crons);
-	update_option('cron', $crons);
-}
-
-function wp_unschedule_event($timestamp, $hook) {
-	$crons = get_option('cron');
-	unset($crons[$timestamp][$hook]);
-	if ( empty($crons[$timestamp]) )
-		unset($crons[$timestamp]);
-	update_option('cron', $crons);
-}
-
-function wp_clear_scheduled_hook($hook) {
-	while($timestamp = next_scheduled('scheduled_hook'))
-		wp_unschedule_event($timestamp, 'scheduled_hook');
-}
-
-function next_scheduled($hook) {
-	$crons = get_option('cron');
-	if ( empty($crons) )
-		return false;
-	foreach($crons as $timestamp => $cron) {
-		//if($timestamp <= time()) continue;
-		if(isset($cron[$hook])) return $timestamp;
-	}
-	return false;
-}
-
-function spawn_cron() {
-	if (array_shift(array_keys(get_option('cron'))) > time()) return;
-
-	$cron_url = get_settings('siteurl') . '/wp-cron.php';
-	$parts = parse_url($cron_url);
-	$argyle = @ fsockopen($parts['host'], $_SERVER['SERVER_PORT'], $errno, $errstr, 0.01);
-	if ( $argyle )
-		fputs($argyle, "GET {$parts['path']}?time=" . time() . '&check='
-		. md5(DB_PASS . '187425') . " HTTP/1.0\r\nHost: {$_SERVER['HTTP_HOST']}\r\n\r\n");
-}
-
-function wp_cron() {
-	$crons = get_option('cron');
-	if (!is_array($crons) || array_shift(array_keys($crons)) > time())
-		return;
-
-	foreach ($crons as $timestamp => $cronhooks) {
-		if ($timestamp > current_time( 'timestamp' )) break;
-		foreach($cronhooks as $hook => $args) {
-			do_action($hook, $args['args']);
-			$recurrence = $args['recur'];
-			if ( 'hourly' == $recurrence ) {
-				$args = array_merge( array($timestamp + 3600, $recurrence, $hook), $args['args']);
-				call_user_func_array('wp_schedule_event', $args);
-			} else if ( 'daily' == $recurrence ) {
-				$args = array_merge( array($timestamp + 86400, $recurrence, $hook), $args['args']);
-				call_user_func_array('wp_schedule_event', $args);
-			}
-
-			wp_unschedule_event($timestamp, $hook);
-		}
-	}
-}
-
 function privacy_ping_filter( $sites ) {
 	if ( get_option('blog_public') )
 		return $sites;
Index: wp-includes/cron.php
===================================================================
--- wp-includes/cron.php	(revision 0)
+++ wp-includes/cron.php	(revision 0)
@@ -0,0 +1,109 @@
+<?php
+function wp_schedule_single_event($timestamp, $hook) {
+	$args = array_slice(func_get_args(), 2);
+	$crons = get_option('cron');
+	$crons[$timestamp][$hook] = array('schedule' => false, 'args' => $args);
+	ksort($crons);
+	update_option('cron', $crons);
+}
+function wp_schedule_new_event($timestamp, $recurrence, $hook) {
+	$args = array_slice(func_get_args(), 3);
+	$crons = get_option('cron');
+	$schedules = wp_get_schedules();
+	if(!isset($schedules[$recurrence]))
+		return false;
+	$crons[$timestamp][$hook] = array('schedule' => $recurrence, 'args' => $args, 'interval' => $schedules[$recurrence]['interval']);
+	ksort($crons);
+	update_option('cron', $crons);
+}
+
+
+function wp_reschedule_event($timestamp, $recurrence, $hook) {
+	$args = array_slice(func_get_args(), 3);
+	$crons = get_option('cron');
+	$schedules = wp_get_schedules();
+	$interval = 0;
+	
+	// First we try to get it from the schedule
+	if( 0 == $interval )
+		$interval = $schedules[$recurrence]['interval'];
+	// Now we try to get it from the saved interval in case the schedule disappears
+	if( 0 == $interval )
+		$interval = $crons[$timestamp][$hook]['interval'];
+	// Now we assume something is wrong and fail to schedule
+	if( 0 == $interval )
+		return false;
+
+	while($timestamp < time() + 1) {
+		$timestamp += $interval;
+	}
+	wp_schedule_new_event($timestamp, $recurrence, $hook);
+}
+
+function wp_unschedule_event($timestamp, $hook) {
+	$crons = get_option('cron');
+	unset($crons[$timestamp][$hook]);
+	if ( empty($crons[$timestamp]) )
+		unset($crons[$timestamp]);
+	update_option('cron', $crons);
+}
+
+function wp_clear_scheduled_hook($hook) {
+	while($timestamp = next_scheduled($hook))
+		wp_unschedule_event($timestamp, $hook);
+}
+
+function wp_next_scheduled($hook) {
+	$crons = get_option('cron');
+	if ( empty($crons) )
+		return false;
+	foreach($crons as $timestamp => $cron) {
+		//if($timestamp <= time()) continue;
+		if(isset($cron[$hook])) return $timestamp;
+	}
+	return false;
+}
+
+function spawn_cron() {
+	if (array_shift(array_keys(get_option('cron'))) > time()) return;
+
+	//Since execute pings had CGI problems, but I'd like to test this without this code first
+	// It seems to be working on CGI here, please report if you have issues
+/*	if ( substr(php_sapi_name(), 0, 3) == 'cgi' ) {
+		echo '<iframe src="' . $cron_url . '"></iframe>';
+	}*/
+	
+	$cron_url = get_settings('siteurl') . '/wp-cron.php';
+	$parts = parse_url($cron_url);
+	
+	$argyle = @ fsockopen($parts['host'], $_SERVER['SERVER_PORT'], $errno, $errstr, 0.01);
+	if ( $argyle )
+		fputs($argyle, "GET {$parts['path']}?time=" . time() . '&check='
+		. md5(DB_PASS . '187425') . " HTTP/1.0\r\nHost: {$_SERVER['HTTP_HOST']}\r\n\r\n");
+}
+
+function wp_cron() {
+	$crons = get_option('cron');
+	if (!is_array($crons) || array_shift(array_keys($crons)) > time())
+		return;
+
+	$schedules = wp_get_schedules();
+	foreach ($crons as $timestamp => $cronhooks) {
+		if ($timestamp > time()) break;
+		foreach($cronhooks as $hook => $args) {
+			if(isset($schedules[$hook]['callback']) && !call_user_func($schedules[$hook]['callback']))
+				continue;
+			spawn_cron();
+			break 2;
+		}
+	}
+}
+
+function wp_get_schedules() {
+	$schedules = array(
+		'hourly' => array('interval' => 3600, 'display' => __('Once Hourly')),
+		'daily' => array('interval' => 86400, 'display' => __('Once Daily')),
+	);
+	return array_merge(apply_filters('cron_schedules', array()), $schedules);
+}
+?>
\ No newline at end of file
Index: wp-cron.php
===================================================================
--- wp-cron.php	(revision 0)
+++ wp-cron.php	(revision 0)
@@ -0,0 +1,22 @@
+<?php
+ignore_user_abort(true);
+define('DOING_CRON', TRUE);
+require_once('wp-config.php');
+
+$crons = get_option('cron');
+if (!is_array($crons) || array_shift(array_keys($crons)) > time())
+	return;
+foreach ($crons as $timestamp => $cronhooks) {
+	if ($timestamp > time()) break;
+	foreach($cronhooks as $hook => $args) {
+		do_action($hook, $args['args']);
+		$schedule = $args['schedule'];
+		if($schedule != false) {
+			fwrite($fp, var_export($schedules[$schedule]));
+			$args = array_merge( array($timestamp, $schedule, $hook), $args['args']);
+			call_user_func_array('wp_reschedule_event', $args);
+		}
+		wp_unschedule_event($timestamp, $hook);
+	}
+}
+?>
Index: wp-includes/functions-post.php
===================================================================
--- wp-includes/functions-post.php	(revision 3630)
+++ wp-includes/functions-post.php	(working copy)
@@ -210,9 +210,10 @@
 				add_post_meta($post_ID, '_wp_page_template',  $page_template, true);
 	}
 
-	if ( 'future' == $post_status )
-		wp_schedule_event(mysql2date('U', $post_date), 'once', 'publish_future_post', $post_ID);
-
+	if ( 'future' == $post_status ) {
+		wp_schedule_single_event(mysql2date('U', $post_date), 'publish_future_post', $post_ID);
+	}
+		
 	do_action('save_post', $post_ID);
 	do_action('wp_insert_post', $post_ID);
 

