diff --git a/boot.php b/boot.php
index 5417e0fa23..b93810d774 100644
--- a/boot.php
+++ b/boot.php
@@ -22,6 +22,7 @@ require_once(__DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'a
 
 use Friendica\App;
 use Friendica\Core\Config;
+use Friendica\Util\Lock;
 
 require_once 'include/config.php';
 require_once 'include/network.php';
@@ -1069,6 +1070,7 @@ function proc_run($cmd) {
 
 	$priority = PRIORITY_MEDIUM;
 	$dont_fork = get_config("system", "worker_dont_fork");
+	$created = datetime_convert();
 
 	if (is_int($run_parameter)) {
 		$priority = $run_parameter;
@@ -1076,6 +1078,9 @@ function proc_run($cmd) {
 		if (isset($run_parameter['priority'])) {
 			$priority = $run_parameter['priority'];
 		}
+		if (isset($run_parameter['created'])) {
+			$created = $run_parameter['created'];
+		}
 		if (isset($run_parameter['dont_fork'])) {
 			$dont_fork = $run_parameter['dont_fork'];
 		}
@@ -1088,7 +1093,7 @@ function proc_run($cmd) {
 	$found = dba::select('workerqueue', array('id'), array('parameter' => $parameters), array('limit' => 1));
 
 	if (!dbm::is_result($found)) {
-		dba::insert('workerqueue', array('parameter' => $parameters, 'created' => datetime_convert(), 'priority' => $priority));
+		dba::insert('workerqueue', array('parameter' => $parameters, 'created' => $created, 'priority' => $priority));
 	}
 
 	// Should we quit and wait for the poller to be called as a cronjob?
@@ -1096,8 +1101,16 @@ function proc_run($cmd) {
 		return;
 	}
 
+	// If there is a lock then we don't have to check for too much worker
+	if (!Lock::set('poller_worker', 0)) {
+		return;
+	}
+
 	// If there are already enough workers running, don't fork another one
-	if (poller_too_much_workers()) {
+	$quit = poller_too_much_workers();
+	Lock::remove('poller_worker');
+
+	if ($quit) {
 		return;
 	}
 
diff --git a/doc/htconfig.md b/doc/htconfig.md
index 9c556bb7cd..ed2c816dea 100644
--- a/doc/htconfig.md
+++ b/doc/htconfig.md
@@ -68,6 +68,7 @@ Example: To set the directory value please add this line to your .htconfig.php:
 * **ostatus_poll_timeframe** - Defines how old an item can be to try to complete the conversation with it.
 * **paranoia** (Boolean) - Log out users if their IP address changed.
 * **permit_crawling** (Boolean) - Restricts the search for not logged in users to one search per minute.
+* **worker_debug** (Boolean) - If enabled, it prints out the number of running processes split by priority.
 * **profiler** (Boolean) - Enable internal timings to help optimize code. Needed for "rendertime" addon. Default is false.
 * **free_crawls** - Number of "free" searches when "permit_crawling" is activated (Default value is 10)
 * **crawl_permit_period** - Period in seconds between allowed searches when the number of free searches is reached and "permit_crawling" is activated (Default value is 60)
diff --git a/include/dba.php b/include/dba.php
index e4846899dc..1c63fa5054 100644
--- a/include/dba.php
+++ b/include/dba.php
@@ -21,6 +21,8 @@ class dba {
 	private $driver;
 	public  $connected = false;
 	public  $error = false;
+	public  $errorno = 0;
+	public  $affected_rows = 0;
 	private $_server_info = '';
 	private static $in_transaction = false;
 	private static $dbo;
@@ -551,6 +553,7 @@ class dba {
 
 		self::$dbo->error = '';
 		self::$dbo->errorno = 0;
+		self::$dbo->affected_rows = 0;
 
 		switch (self::$dbo->driver) {
 			case 'pdo':
@@ -573,6 +576,7 @@ class dba {
 					$retval = false;
 				} else {
 					$retval = $stmt;
+					self::$dbo->affected_rows = $retval->rowCount();
 				}
 				break;
 			case 'mysqli':
@@ -612,6 +616,7 @@ class dba {
 				} else {
 					$stmt->store_result();
 					$retval = $stmt;
+					self::$dbo->affected_rows = $retval->affected_rows;
 				}
 				break;
 			case 'mysql':
@@ -620,13 +625,28 @@ class dba {
 				if (mysql_errno(self::$dbo->db)) {
 					self::$dbo->error = mysql_error(self::$dbo->db);
 					self::$dbo->errorno = mysql_errno(self::$dbo->db);
+				} else {
+					self::$dbo->affected_rows = mysql_affected_rows($retval);
 				}
 				break;
 		}
 
 		if (self::$dbo->errorno != 0) {
-			logger('DB Error '.self::$dbo->errorno.': '.self::$dbo->error."\n".
-				$a->callstack(8))."\n".self::replace_parameters($sql, $args);
+			$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
+			$called_from = array_shift($trace);
+
+			// We are having an own error logging in the function "p"
+			if ($called_from['function'] != 'p') {
+				// We have to preserve the error code, somewhere in the logging it get lost
+				$error = self::$dbo->error;
+				$errorno = self::$dbo->errorno;
+
+				logger('DB Error '.self::$dbo->errorno.': '.self::$dbo->error."\n".
+					$a->callstack(8))."\n".self::replace_parameters($sql, $args);
+
+				self::$dbo->error = $error;
+				self::$dbo->errorno = $errorno;
+			}
 		}
 
 		$a->save_timestamp($stamp1, 'database');
@@ -662,18 +682,36 @@ class dba {
 
 		$args = func_get_args();
 
-		$stmt = call_user_func_array('self::p', $args);
+		// In a case of a deadlock we are repeating the query 20 times
+		$timeout = 20;
 
-		if (is_bool($stmt)) {
-			$retval = $stmt;
-		} elseif (is_object($stmt)) {
-			$retval = true;
-		} else {
-			$retval = false;
+		do {
+			$stmt = call_user_func_array('self::p', $args);
+
+			if (is_bool($stmt)) {
+				$retval = $stmt;
+			} elseif (is_object($stmt)) {
+				$retval = true;
+			} else {
+				$retval = false;
+			}
+
+			self::close($stmt);
+
+		} while ((self::$dbo->errorno == 1213) && (--$timeout > 0));
+
+		if (self::$dbo->errorno != 0) {
+			// We have to preserve the error code, somewhere in the logging it get lost
+			$error = self::$dbo->error;
+			$errorno = self::$dbo->errorno;
+
+			logger('DB Error '.self::$dbo->errorno.': '.self::$dbo->error."\n".
+				$a->callstack(8))."\n".self::replace_parameters($sql, $args);
+
+			self::$dbo->error = $error;
+			self::$dbo->errorno = $errorno;
 		}
 
-		self::close($stmt);
-
 		$a->save_timestamp($stamp, "database_write");
 
 		return $retval;
@@ -723,6 +761,15 @@ class dba {
 		return $retval;
 	}
 
+	/**
+	 * @brief Returns the number of affected rows of the last statement
+	 *
+	 * @return int Number of rows
+	 */
+	static public function affected_rows() {
+		return self::$dbo->affected_rows;
+	}
+
 	/**
 	 * @brief Returns the number of rows of a statement
 	 *
diff --git a/include/items.php b/include/items.php
index eb30763909..8649a1bd1a 100644
--- a/include/items.php
+++ b/include/items.php
@@ -1139,7 +1139,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f
 	check_item_notification($current_post, $uid);
 
 	if ($notify) {
-		proc_run(PRIORITY_HIGH, "include/notifier.php", $notify_type, $current_post);
+		proc_run(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "include/notifier.php", $notify_type, $current_post);
 	}
 
 	return $current_post;
@@ -1430,7 +1430,7 @@ function tag_deliver($uid, $item_id) {
 	);
 	update_thread($item_id);
 
-	proc_run(PRIORITY_HIGH,'include/notifier.php', 'tgroup', $item_id);
+	proc_run(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), 'include/notifier.php', 'tgroup', $item_id);
 
 }
 
@@ -2076,7 +2076,7 @@ function item_expire($uid, $days, $network = "", $force = false) {
 		drop_item($item['id'], false);
 	}
 
-	proc_run(PRIORITY_LOW, "include/notifier.php", "expire", $uid);
+	proc_run(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "include/notifier.php", "expire", $uid);
 
 }
 
@@ -2099,7 +2099,7 @@ function drop_items($items) {
 	// multiple threads may have been deleted, send an expire notification
 
 	if ($uid) {
-		proc_run(PRIORITY_LOW, "include/notifier.php", "expire", $uid);
+		proc_run(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "include/notifier.php", "expire", $uid);
 	}
 }
 
@@ -2295,7 +2295,7 @@ function drop_item($id, $interactive = true) {
 		$drop_id = intval($item['id']);
 		$priority = ($interactive ? PRIORITY_HIGH : PRIORITY_LOW);
 
-		proc_run($priority, "include/notifier.php", "drop", $drop_id);
+		proc_run(array('priority' => $priority, 'dont_fork' => true), "include/notifier.php", "drop", $drop_id);
 
 		if (! $interactive) {
 			return $owner;
diff --git a/include/notifier.php b/include/notifier.php
index 7f6318182f..c110984dde 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -55,17 +55,6 @@ function notifier_run(&$argv, &$argc){
 		return;
 	}
 
-	// Inherit the priority
-	$queue = dba::select('workerqueue', array('priority'), array('pid' => getmypid()), array('limit' => 1));
-	if (dbm::is_result($queue)) {
-		$priority = (int)$queue['priority'];
-		logger('inherited priority: '.$priority);
-	} else {
-		// Normally this shouldn't happen.
-		$priority = PRIORITY_HIGH;
-		logger('no inherited priority! Something is wrong.');
-	}
-
 	logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
 
 	$cmd = $argv[1];
@@ -359,7 +348,7 @@ function notifier_run(&$argv, &$argc){
 			// a delivery fork. private groups (forum_mode == 2) do not uplink
 
 			if ((intval($parent['forum_mode']) == 1) && (! $top_level) && ($cmd !== 'uplink')) {
-				proc_run($priority, 'include/notifier.php', 'uplink', $item_id);
+				proc_run($a->queue['priority'], 'include/notifier.php', 'uplink', $item_id);
 			}
 
 			$conversants = array();
@@ -498,7 +487,8 @@ function notifier_run(&$argv, &$argc){
 			}
 			logger("Deliver ".$target_item["guid"]." to ".$contact['url']." via network ".$contact['network'], LOGGER_DEBUG);
 
-			proc_run(array('priority' => $priority, 'dont_fork' => true), 'include/delivery.php', $cmd, $item_id, $contact['id']);
+			proc_run(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true),
+					'include/delivery.php', $cmd, $item_id, (int)$contact['id']);
 		}
 	}
 
@@ -563,7 +553,8 @@ function notifier_run(&$argv, &$argc){
 
 				if ((! $mail) && (! $fsuggest) && (! $followup)) {
 					logger('notifier: delivery agent: '.$rr['name'].' '.$rr['id'].' '.$rr['network'].' '.$target_item["guid"]);
-					proc_run(array('priority' => $priority, 'dont_fork' => true), 'include/delivery.php', $cmd, $item_id, $rr['id']);
+					proc_run(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true),
+							'include/delivery.php', $cmd, $item_id, (int)$rr['id']);
 				}
 			}
 		}
@@ -603,7 +594,8 @@ function notifier_run(&$argv, &$argc){
 		}
 
 		// Handling the pubsubhubbub requests
-		proc_run(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), 'include/pubsubpublish.php');
+		proc_run(array('priority' => PRIORITY_HIGH, 'created' => $a->queue['created'], 'dont_fork' => true),
+				'include/pubsubpublish.php');
 	}
 
 	logger('notifier: calling hooks', LOGGER_DEBUG);
diff --git a/include/poller.php b/include/poller.php
index cc8edce656..ef6fbd69de 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -47,11 +47,15 @@ function poller_run($argv, $argc){
 	// We now start the process. This is done after the load check since this could increase the load.
 	$a->start_process();
 
-	// At first we check the number of workers and quit if there are too much of them
-	// This is done at the top to avoid that too much code is executed without a need to do so,
-	// since the poller mostly quits here.
-	if (poller_too_much_workers()) {
+	// Kill stale processes every 5 minutes
+	$last_cleanup = Config::get('system', 'poller_last_cleaned', 0);
+	if (time() > ($last_cleanup + 300)) {
+		Config::set('system', 'poller_last_cleaned', time());
 		poller_kill_stale_workers();
+	}
+
+	// Count active workers and compare them with a maximum value that depends on the load
+	if (poller_too_much_workers()) {
 		logger('Pre check: Active worker limit reached, quitting.', LOGGER_DEBUG);
 		return;
 	}
@@ -83,10 +87,15 @@ function poller_run($argv, $argc){
 
 	// We fetch the next queue entry that is about to be executed
 	while ($r = poller_worker_process()) {
+		foreach ($r AS $entry) {
+			// Assure that the priority is an integer value
+			$entry['priority'] = (int)$entry['priority'];
 
-		// If we got that queue entry we claim it for us
-		if (!poller_claim_process($r[0])) {
-			continue;
+			// The work will be done
+			if (!poller_execute($entry)) {
+				logger('Process execution failed, quitting.', LOGGER_DEBUG);
+				return;
+			}
 		}
 
 		// To avoid the quitting of multiple pollers only one poller at a time will execute the check
@@ -105,14 +114,8 @@ function poller_run($argv, $argc){
 			Lock::remove('poller_worker');
 		}
 
-		// finally the work will be done
-		if (!poller_execute($r[0])) {
-			logger('Process execution failed, quitting.', LOGGER_DEBUG);
-			return;
-		}
-
-		// Quit the poller once every hour
-		if (time() > ($starttime + 3600)) {
+		// Quit the poller once every 5 minutes
+		if (time() > ($starttime + 300)) {
 			logger('Process lifetime reached, quitting.', LOGGER_DEBUG);
 			return;
 		}
@@ -120,6 +123,47 @@ function poller_run($argv, $argc){
 	logger("Couldn't select a workerqueue entry, quitting.", LOGGER_DEBUG);
 }
 
+/**
+ * @brief Returns the number of non executed entries in the worker queue
+ *
+ * @return integer Number of non executed entries in the worker queue
+ */
+function poller_total_entries() {
+	$s = q("SELECT COUNT(*) AS `total` FROM `workerqueue` WHERE `executed` <= '%s'", dbesc(NULL_DATE));
+	if (dbm::is_result($s)) {
+		return $s[0]["total"];
+	} else {
+		return 0;
+	}
+}
+
+/**
+ * @brief Returns the highest priority in the worker queue that isn't executed
+ *
+ * @return integer Number of active poller processes
+ */
+function poller_highest_priority() {
+	$s = q("SELECT `priority` FROM `workerqueue` WHERE `executed` <= '%s' ORDER BY `priority` LIMIT 1", dbesc(NULL_DATE));
+	if (dbm::is_result($s)) {
+		return $s[0]["priority"];
+	} else {
+		return 0;
+	}
+}
+
+/**
+ * @brief Returns if a process with the given priority is running
+ *
+ * @param integer $priority The priority that should be checked
+ *
+ * @return integer Is there a process running with that priority?
+ */
+function poller_process_with_priority_active($priority) {
+	$s = q("SELECT `id` FROM `workerqueue` WHERE `priority` <= %d AND `executed` > '%s' LIMIT 1",
+			intval($priority), dbesc(NULL_DATE));
+	return dbm::is_result($s);
+}
+
 /**
  * @brief Execute a worker entry
  *
@@ -214,10 +258,12 @@ function poller_exec_function($queue, $funcname, $argv) {
 	// But preserve the old one for the worker
 	$old_process_id = $a->process_id;
 	$a->process_id = uniqid("wrk", true);
+	$a->queue = $queue;
 
 	$funcname($argv, $argc);
 
 	$a->process_id = $old_process_id;
+	unset($a->queue);
 
 	$duration = number_format(microtime(true) - $stamp, 3);
 
@@ -442,38 +488,35 @@ function poller_too_much_workers() {
 		$slope = $maxworkers / pow($maxsysload, $exponent);
 		$queues = ceil($slope * pow(max(0, $maxsysload - $load), $exponent));
 
-		// Create a list of queue entries grouped by their priority
-		$listitem = array();
+		if (Config::get('system', 'worker_debug')) {
+			// Create a list of queue entries grouped by their priority
+			$listitem = array();
 
-		// Adding all processes with no workerqueue entry
-		$processes = dba::p("SELECT COUNT(*) AS `running` FROM `process` WHERE NOT EXISTS (SELECT id FROM `workerqueue` WHERE `workerqueue`.`pid` = `process`.`pid`)");
-		if ($process = dba::fetch($processes)) {
-			$listitem[0] = "0:".$process["running"];
-		}
-		dba::close($processes);
-
-		// Now adding all processes with workerqueue entries
-		$entries = dba::p("SELECT COUNT(*) AS `entries`, `priority` FROM `workerqueue` GROUP BY `priority`");
-		while ($entry = dba::fetch($entries)) {
-			$processes = dba::p("SELECT COUNT(*) AS `running` FROM `process` INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid` WHERE `priority` = ?", $entry["priority"]);
+			// Adding all processes with no workerqueue entry
+			$processes = dba::p("SELECT COUNT(*) AS `running` FROM `process` WHERE NOT EXISTS (SELECT id FROM `workerqueue` WHERE `workerqueue`.`pid` = `process`.`pid`)");
 			if ($process = dba::fetch($processes)) {
-				$listitem[$entry["priority"]] = $entry["priority"].":".$process["running"]."/".$entry["entries"];
+				$listitem[0] = "0:".$process["running"];
 			}
 			dba::close($processes);
-		}
-		dba::close($entries);
-		$processlist = ' ('.implode(', ', $listitem).')';
 
-		$s = q("SELECT COUNT(*) AS `total` FROM `workerqueue` WHERE `executed` <= '%s'", dbesc(NULL_DATE));
-		$entries = $s[0]["total"];
+			// Now adding all processes with workerqueue entries
+			$entries = dba::p("SELECT COUNT(*) AS `entries`, `priority` FROM `workerqueue` GROUP BY `priority`");
+			while ($entry = dba::fetch($entries)) {
+				$processes = dba::p("SELECT COUNT(*) AS `running` FROM `process` INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid` WHERE `priority` = ?", $entry["priority"]);
+				if ($process = dba::fetch($processes)) {
+					$listitem[$entry["priority"]] = $entry["priority"].":".$process["running"]."/".$entry["entries"];
+				}
+				dba::close($processes);
+			}
+			dba::close($entries);
+			$processlist = ' ('.implode(', ', $listitem).')';
+		}
+
+		$entries = poller_total_entries();
 
 		if (Config::get("system", "worker_fastlane", false) && ($queues > 0) && ($entries > 0) && ($active >= $queues)) {
-			$s = q("SELECT `priority` FROM `workerqueue` WHERE `executed` <= '%s' ORDER BY `priority` LIMIT 1", dbesc(NULL_DATE));
-			$top_priority = $s[0]["priority"];
-
-			$s = q("SELECT `id` FROM `workerqueue` WHERE `priority` <= %d AND `executed` > '%s' LIMIT 1",
-				intval($top_priority), dbesc(NULL_DATE));
-			$high_running = dbm::is_result($s);
+			$top_priority = poller_highest_priority();
+			$high_running = poller_process_with_priority_active($top_priority);
 
 			if (!$high_running && ($top_priority > PRIORITY_UNDEFINED) && ($top_priority < PRIORITY_NEGLIGIBLE)) {
 				logger("There are jobs with priority ".$top_priority." waiting but none is executed. Open a fastlane.", LOGGER_DEBUG);
@@ -557,6 +600,49 @@ function poller_passing_slow(&$highest_priority) {
 	return $passing_slow;
 }
 
+/**
+ * @brief Find and claim the next worker process for us
+ *
+ * @return boolean Have we found something?
+ */
+function find_worker_processes() {
+	// Check if we should pass some low priority process
+	$highest_priority = 0;
+	$found = false;
+
+	if (poller_passing_slow($highest_priority)) {
+		// Are there waiting processes with a higher priority than the currently highest?
+		$result = dba::e("UPDATE `workerqueue` SET `executed` = ?, `pid` = ?
+					WHERE `executed` <= ? AND `priority` < ?
+					ORDER BY `priority`, `created` LIMIT 5",
+				datetime_convert(), getmypid(), NULL_DATE, $highest_priority);
+		if ($result) {
+			$found = (dba::affected_rows() > 0);
+		}
+
+		if (!$found) {
+			// Give slower processes some processing time
+			$result = dba::e("UPDATE `workerqueue` SET `executed` = ?, `pid` = ?
+						WHERE `executed` <= ? AND `priority` > ?
+						ORDER BY `priority`, `created` LIMIT 1",
+					datetime_convert(), getmypid(), NULL_DATE, $highest_priority);
+			if ($result) {
+				$found = (dba::affected_rows() > 0);
+			}
+		}
+	}
+
+	// If there is no result (or we shouldn't pass lower processes) we check without priority limit
+	if (!$found) {
+		$result = dba::e("UPDATE `workerqueue` SET `executed` = ?, `pid` = ? WHERE `executed` <= ? ORDER BY `priority`, `created` LIMIT 5",
+				datetime_convert(), getmypid(), NULL_DATE);
+		if ($result) {
+			$found = (dba::affected_rows() > 0);
+		}
+	}
+	return $found;
+}
+
 /**
  * @brief Returns the next worker process
  *
@@ -564,84 +650,18 @@ function poller_passing_slow(&$highest_priority) {
  */
 function poller_worker_process() {
 
-	// Check if we should pass some low priority process
-	$highest_priority = 0;
+	$stamp = (float)microtime(true);
 
-	if (poller_passing_slow($highest_priority)) {
-		dba::lock('workerqueue');
+	$found = find_worker_processes();
 
-		// Are there waiting processes with a higher priority than the currently highest?
-		$r = q("SELECT * FROM `workerqueue`
-				WHERE `executed` <= '%s' AND `priority` < %d
-				ORDER BY `priority`, `created` LIMIT 1",
-				dbesc(NULL_DATE),
-				intval($highest_priority));
-		if (dbm::is_result($r)) {
-			return $r;
-		}
-		// Give slower processes some processing time
-		$r = q("SELECT * FROM `workerqueue`
-				WHERE `executed` <= '%s' AND `priority` > %d
-				ORDER BY `priority`, `created` LIMIT 1",
-				dbesc(NULL_DATE),
-				intval($highest_priority));
+	logger('Duration: '.number_format(microtime(true) - $stamp, 3), LOGGER_DEBUG);
 
-		if (dbm::is_result($r)) {
-			return $r;
-		}
-	} else {
-		dba::lock('workerqueue');
+	if ($found) {
+		$r = q("SELECT * FROM `workerqueue` WHERE `pid` = %d", intval(getmypid()));
 	}
-
-	// If there is no result (or we shouldn't pass lower processes) we check without priority limit
-	if (!dbm::is_result($r)) {
-		$r = q("SELECT * FROM `workerqueue` WHERE `executed` <= '%s' ORDER BY `priority`, `created` LIMIT 1", dbesc(NULL_DATE));
-	}
-
-	// We only unlock the tables here, when we got no data
-	if (!dbm::is_result($r)) {
-		dba::unlock();
-	}
-
 	return $r;
 }
 
-/**
- * @brief Assigns a workerqueue entry to the current process
- *
- * When we are sure that the table locks are working correctly, we can remove the checks from here
- *
- * @param array $queue Workerqueue entry
- *
- * @return boolean "true" if the claiming was successful
- */
-function poller_claim_process($queue) {
-	$mypid = getmypid();
-
-	$success = dba::update('workerqueue', array('executed' => datetime_convert(), 'pid' => $mypid),
-			array('id' => $queue["id"], 'pid' => 0));
-	dba::unlock();
-
-	if (!$success) {
-		logger("Couldn't update queue entry ".$queue["id"]." - skip this execution", LOGGER_DEBUG);
-		return false;
-	}
-
-	// Assure that there are no tasks executed twice
-	$id = q("SELECT `pid`, `executed` FROM `workerqueue` WHERE `id` = %d", intval($queue["id"]));
-	if (!$id) {
-		logger("Queue item ".$queue["id"]." vanished - skip this execution", LOGGER_DEBUG);
-		return false;
-	} elseif ((strtotime($id[0]["executed"]) <= 0) || ($id[0]["pid"] == 0)) {
-		logger("Entry for queue item ".$queue["id"]." wasn't stored - skip this execution", LOGGER_DEBUG);
-		return false;
-	} elseif ($id[0]["pid"] != $mypid) {
-		logger("Queue item ".$queue["id"]." is to be executed by process ".$id[0]["pid"]." and not by me (".$mypid.") - skip this execution", LOGGER_DEBUG);
-		return false;
-	}
-	return true;
-}
-
 /**
  * @brief Removes a workerqueue entry from the current process
  */
diff --git a/include/pubsubpublish.php b/include/pubsubpublish.php
index 1112969f27..580e3ffce1 100644
--- a/include/pubsubpublish.php
+++ b/include/pubsubpublish.php
@@ -7,6 +7,7 @@ require_once('include/items.php');
 require_once('include/ostatus.php');
 
 function pubsubpublish_run(&$argv, &$argc){
+	global $a;
 
 	if ($argc > 1) {
 		$pubsubpublish_id = intval($argv[1]);
@@ -17,7 +18,8 @@ function pubsubpublish_run(&$argv, &$argc){
 
 		foreach ($r as $rr) {
 			logger("Publish feed to ".$rr["callback_url"], LOGGER_DEBUG);
-			proc_run(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), 'include/pubsubpublish.php', $rr["id"]);
+			proc_run(array('priority' => PRIORITY_HIGH, 'created' => $a->queue['created'], 'dont_fork' => true),
+					'include/pubsubpublish.php', (int)$rr["id"]);
 		}
 	}
 
diff --git a/src/App.php b/src/App.php
index f6b568ae8a..94ca007511 100644
--- a/src/App.php
+++ b/src/App.php
@@ -100,6 +100,7 @@ class App {
 	 */
 	public $template_engine_instance = array();
 	public $process_id;
+	public $queue;
 	private $ldelim = array(
 		'internal' => '',
 		'smarty3' => '{{'
diff --git a/src/Util/Lock.php b/src/Util/Lock.php
index b2c5afc662..36f408cf32 100644
--- a/src/Util/Lock.php
+++ b/src/Util/Lock.php
@@ -57,10 +57,11 @@ class Lock {
 
 		$memcache = self::connectMemcache();
 		if (is_object($memcache)) {
-			$wait_sec = 0.2;
 			$cachekey = get_app()->get_hostname().";lock:".$fn_name;
 
 			do {
+				// We only lock to be sure that nothing happens at exactly the same time
+				dba::lock('locks');
 				$lock = $memcache->get($cachekey);
 
 				if (!is_bool($lock)) {
@@ -76,16 +77,17 @@ class Lock {
 					$memcache->set($cachekey, getmypid(), MEMCACHE_COMPRESSED, 300);
 					$got_lock = true;
 				}
+
+				dba::unlock();
+
 				if (!$got_lock && ($timeout > 0)) {
-					usleep($wait_sec * 1000000);
+					usleep(rand(10000, 200000));
 				}
 			} while (!$got_lock && ((time() - $start) < $timeout));
 
 			return $got_lock;
 		}
 
-		$wait_sec = 2;
-
 		do {
 			dba::lock('locks');
 			$lock = dba::select('locks', array('locked', 'pid'), array('name' => $fn_name), array('limit' => 1));
@@ -113,7 +115,7 @@ class Lock {
 			dba::unlock();
 
 			if (!$got_lock && ($timeout > 0)) {
-				sleep($wait_sec);
+				usleep(rand(100000, 2000000));
 			}
 		} while (!$got_lock && ((time() - $start) < $timeout));