]> git.mxchange.org Git - friendica.git/commitdiff
add some timeouts to prevent deadlock
authorZach Prezkuta <fermion@gmx.com>
Fri, 6 Jul 2012 01:01:13 +0000 (19:01 -0600)
committerZach Prezkuta <fermion@gmx.com>
Fri, 6 Jul 2012 01:01:13 +0000 (19:01 -0600)
include/diaspora.php
include/lock.php

index 29846eedf6918a609eb93ad5098a8170bee9300a..35cd660596427822e8fb653dca1510f53036caaa 100755 (executable)
@@ -119,6 +119,9 @@ function find_diaspora_person_by_handle($handle) {
        $update = false;
        $got_lock = false;
 
+       $endlessloop = 0;
+       $maxloops = 10;
+
        do {
                $r = q("select * from fcontact where network = '%s' and addr = '%s' limit 1",
                        dbesc(NETWORK_DIASPORA),
@@ -153,7 +156,12 @@ function find_diaspora_person_by_handle($handle) {
                        // Lock the function to prevent race conditions if multiple items
                        // come in at the same time from a person who doesn't exist in
                        // fcontact
-                       $got_lock = lock_function('find_diaspora_person_by_handle', false);
+                       //
+                       // Don't loop forever. On the last loop, try to create the contact
+                       // whether the function is locked or not. Maybe the locking thread
+                       // has died or something. At any rate, a duplicate in 'fcontact'
+                       // is a much smaller problem than a deadlocked thread
+                       $got_lock = (($endlessloop + 1) < $maxloops ? lock_function('find_diaspora_person_by_handle', false) : true );
 
                        if($got_lock) {
                                logger('find_diaspora_person_by_handle: create or refresh', LOGGER_DEBUG);
@@ -175,7 +183,7 @@ function find_diaspora_person_by_handle($handle) {
                                        block_on_function_lock('find_diaspora_person_by_handle');
                        }
                }
-       } while((! $person) && (! $got_lock));
+       } while((! $person) && (! $got_lock) && (++$endlessloop < $maxloops));
        // We need to try again if the person wasn't in 'fcontact' but the function was locked.
        // The fact that the function was locked may mean that another process was creating the
        // person's record. It could also mean another process was creating or updating an unrelated
index 9bdb71125af64b236ad32c6d7d50d4e0ade517f9..5f1ca63231123a87dac5cceb165c9edf253a6583 100644 (file)
@@ -3,11 +3,12 @@
 // Provide some ability to lock a PHP function so that multiple processes
 // can't run the function concurrently
 if(! function_exists('lock_function')) {
-function lock_function($fn_name, $block = true, $wait_sec = 2) {
+function lock_function($fn_name, $block = true, $wait_sec = 2, $timeout = 30) {
        if( $wait_sec == 0 )
                $wait_sec = 2;  // don't let the user pick a value that's likely to crash the system
 
        $got_lock = false;
+       $start = time();
 
        do {
                q("LOCK TABLE locks WRITE");
@@ -33,19 +34,21 @@ function lock_function($fn_name, $block = true, $wait_sec = 2) {
                if(($block) && (! $got_lock))
                        sleep($wait_sec);
 
-       } while(($block) && (! $got_lock));
+       } while(($block) && (! $got_lock) && ((time() - $start) < $timeout));
 
-       logger('lock_function: function ' . $fn_name . ' with blocking = ' . $block . ' got_lock = ' . $got_lock, LOGGER_DEBUG);
+       logger('lock_function: function ' . $fn_name . ' with blocking = ' . $block . ' got_lock = ' . $got_lock . ' time = ' . (time() - $start), LOGGER_DEBUG);
        
        return $got_lock;
 }}
 
 
 if(! function_exists('block_on_function_lock')) {
-function block_on_function_lock($fn_name, $wait_sec = 2) {
+function block_on_function_lock($fn_name, $wait_sec = 2, $timeout = 30) {
        if( $wait_sec == 0 )
                $wait_sec = 2;  // don't let the user pick a value that's likely to crash the system
 
+       $start = time();
+
        do {
                $r = q("SELECT locked FROM locks WHERE name = '%s' LIMIT 1",
                                dbesc($fn_name)
@@ -54,7 +57,7 @@ function block_on_function_lock($fn_name, $wait_sec = 2) {
                if(count($r) && $r[0]['locked'])
                        sleep($wait_sec);
 
-       } while(count($r) && $r[0]['locked']);
+       } while(count($r) && $r[0]['locked'] && ((time() - $start) < $timeout));
 
        return;
 }}
@@ -62,11 +65,9 @@ function block_on_function_lock($fn_name, $wait_sec = 2) {
 
 if(! function_exists('unlock_function')) {
 function unlock_function($fn_name) {
-       //$r = q("LOCK TABLE lock WRITE");
        $r = q("UPDATE locks SET locked = 0 WHERE name = '%s' LIMIT 1",
                        dbesc($fn_name)
             );
-       //$r = q("UNLOCK TABLES");
 
        logger('unlock_function: released lock for function ' . $fn_name, LOGGER_DEBUG);