I've never seen a SegFault in PHP before today, but apparently it's possible. At first I thought it was mysql driver, but it turned out it was my code ;).
I spent about 2 days debugging my code and finally tracked it down to it's cause (so to all you future PHP programmers who run into this, you are welcome!)
Long story short, you CAN'T do an unset()
on the same array your are walking while you're doing array_walk()
.
The purpose is to eliminate all elements from $this->votes that don't exist in the $out array (where the key of $this->votes matches to the id property of one of the elements in $out).
The Problem I was having was about half the time the code would run fine, and the other half it would crash with a Segmentation Fault in the apache log (making it pretty hard to debug because it was a while until I noticed this error).
And yea, it's a pretty poorly thought out piece of code to begin with....
array_walk($this->votes, function(&$o, $key) use($that, $out) {
$found = array_filter($out, function($p) use($key) {
return $p['id'] == $key;
});
if(count($found) == 0) {
unset($this->votes[$key]); //very very bad!!!!
}
});
As I understand it, what ends up happening is unset()
messes up the $this->vote
s array length. array_walk
uses an iterator which expects the $this->votes
array to remain the same length throughout the entire walk. If I wrote my own array_walk
function (for ($i = 0; $i < count($this->votes); $i++
) it would just throw an undefined index notice. But since we are using array_walk
it will actually try to look in a location in memory which may or may not have some data. This can cause the unpredictability of the function (sometimes the code can run just fine, other times it will cause a seg fault).
So the RIGHT way to do it would be
$tmpVotes = array();
array_walk($this->votes, function(&$o, $key) use($that, $out, $tmpVotes) {
$found = array_filter($out, function($p) use($key, $that, $tmpVotes) {
return $p['id'] == $key;
});
if(count($found) > 0) {
$tpmVotes[$key] = $o;
}
});
$this->votes = $tmpVotes;
From PHP Manual:
Only the values of the array may potentially be changed; its structure cannot be altered, i.e., the programmer cannot add, unset or reorder elements. If the callback does not respect this requirement, the behavior of this function is undefined, and unpredictable.
If anyone has a better way of explaining what happens here, please post!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With