PHP-Counter resettet immer wieder

24/02/2011 - 23:56 von Jens Fittig | Report spam
Hallo, ich nutze folgenden Code für einen Counter:

function increase_save_count() {
if (!file_exists(PFAD."counter_files/count.txt")) {
error("no_counter_file");
} elseif (!is_writable(PFAD."counter_files/count.txt")) {
error("count_unwriteable");
} else {
$counts = file(PFAD."counter_files/count.txt");
$count = trim($counts[0]);
$count++;
$fh = fopen(PFAD."counter_files/count.txt","wb");
flock($fh, LOCK_EX);
fwrite($fh, $count);
fclose($fh);


$string = $count . " " . date("H:i:s",time(TRUE)) . " " .
$_SERVER[ "REMOTE_ADDR" ] . "" ;
$logfile = PFAD."counter_files/countlog.txt";
$fh = fopen($logfile,"a");
flock($fh, LOCK_EX);
fwrite($fh, $string);
fclose($fh);

}
return;
}


Dieser Counter springt so alle paar tausend Counts, aber unregelmàßig,
auf "0".

Wie kann das passieren? Wie kann ich das verhindern?

Der Code stammt aus einer fertigen Codeschnipselsammlung. Ich habe nur
den Zusatz bezüglich der Mitspeicherung im "countlog" drangehàngt
damit ch den Counter anhand des Logfiles wieder neu setzen kann.

Ein àhnliches Script in einer anderen Webseite per Perl/CGI hat das
selbe Problem. Alle paat zehntausend counts springt es willkürlich auf
"0"
 

Lesen sie die antworten

#1 Marcel Müller
25/02/2011 - 01:06 | Warnen spam
Jens Fittig wrote:
Dieser Counter springt so alle paar tausend Counts, aber unregelmàßig,
auf "0".

Wie kann das passieren? Wie kann ich das verhindern?



Klassische Race-Condition. Die Erhöhung des Counters erfolgt
unsynchronisiert. Wenn das mehrere gleichzeitig tun, ist es nur eine
Frage der Zeit, bis es knallt. Mutmaßlich hat er sich, bis er wieder bei
null anfàngt auch schon einige male verzàhlt (Counts vergessen).

Verhindert tut man das, indem der Zugriff synchronisiert wird. Für
Zàhler benötigt man atomare read-modify-write Zyklen. Also:
- Datei öffnen, Access-Modus read/write ("r+"), Share-Modus DenyNone
- Datei sperren (flock), ggf. warten bis die Datei frei ist.
- Datei lesen (vmtl. fread oder fgets)
- Counter erhöhen
- Dateipointer zurücksetzen (vmtl fseek oder rewind)
- Datei schließen

Ich kenne PHP nicht, deshalb kenne ich die genauen Methodennamen nicht.
Es muss auch überprüft werden, ob flock im Fall einer Kollision wartet,
bis die Datei wieder frei ist, oder ob es einen Fehler zurückliefert,
der im Code großzügig ignoriert wird.


Der Code stammt aus einer fertigen Codeschnipselsammlung.



Fehlerhafte Codeschnipsel, wie es aussieht.


Ein àhnliches Script in einer anderen Webseite per Perl/CGI hat das
selbe Problem. Alle paat zehntausend counts springt es willkürlich auf
"0"



Logisch, der Code ist falsch.


Marcel

Ähnliche fragen