Related
On our platform, users may have different combinations of products in their inventory. Every now and then, a user will report to us that the page that lists these products is crashing. What this "crashing" actually is is PHP just stoping the rendering of a product for no reason at all, and then not rendering the rest of the page (for example, PHP won't include the footer file, so the page just ends at the half-rendered product).
Sometimes it stops at a random product after rendering it fully, sometimes it only renders a product's image and stops the whole page rendering there.
Seemingly random changes to the code seem to make the crashing stop. What do I mean?
If I add this anywhere inside the product loop:
<?php echo "<script>console.log('test');</script>"; ?>
It will stop the error. Just today I decided turning php.ini's display errors on and that fixed the error for some dude. Turning it off brought it back. Some other user was fixed when I changed the loop's syntax from
<?php foreach ($inventory as $code) : ?>
to
<?php
foreach ($inventory as $code)
{
This is the current code for the loop:
<div class="myProductsList">
<?php
$inventory = GetUserInventory($user, $plan);
if ($inventory)
{
$evenOdd = false;
foreach ($inventory as $code)
{
$product = GetProductObject($code, $plan);
$product = $product[0]->ID;
if ($product)
{
$prdTitle = get_the_title($product);
$prdDate = get_the_date('F, Y', $product);
$prdImg = get_the_post_thumbnail_url($product);
$prdLink = str_replace('/offer/', '/product/', get_the_permalink($product));
$evenOdd = !$evenOdd;
$tagCloud = get_field("prd_tagcloud", $product);
$owner = false;
include 'parts/product-card.php';
}
}
}
?>
</div>
And this is the current code for the product-card
<div class="productCard altCard_<?=$evenOdd;?> <?=$owner;?>" stamp="<?=get_the_date('U', $product);?>">
<div class="productCardCont fullw fullh cont col">
<a href="<?=$prdLink;?>">
<img class="fullw" src="<?=$prdImg;?>">
</a>
<div class="productCardAbout fullw hcent cont col npad">
<h3 class="fullw fcent"><?=$prdTitle;?></h3>
<span class="fullw fcent"><?=$prdDate;?></span>
<div class="productCardWarp"></div>
<div class="ctaMain cont col hcent" id="#ctaMain">
<?=ctaMain($prdLink, "Select");?>
</div>
</div>
<span style="display:none!important;"><?=$tagCloud;?></span>
</div>
</div>
I have absoulutely no idea what causes this, especially since no errors appear when I turn them on, no product has any invalid or corrupted data (as you can see I only pull their images, names and date), no inventory code is ever wrong, we have very few users compared to our VM's specs capabilities, the page always loads blazing fast, and as I said:
Random users, with seemingly nothing in common experience these issues, and the 'fixes' often make no sense at all.
One last thing. Sometimes in order to investigate these error reports, I will copy the user's inventory and set it to my own test account (so we both have a identical inventory). Sometimes my account experiences the error, sometimes it doesn't.
The "inventory" I talk about is a table in our database, where each user has a row, and the inventory is just a comma separeated sequence of our internal codes for each products. The codes are a simple number-letter combination.
Example of a inventory that has caused my account to crash:
F2112S04E6B,F2105S03E05,FL21M03V2,F2106S03E06,F2107S04E01,FL20M03V1,F2109S04E03,F2110S04E04,F2111S04E05,F2202S05E02,F2006S1E00,F2208S06E02,F2209S06E03,
Sometimes, if I remove a random product from it, it stops crashing.
PHP version: PHP 8.0.18
Database: 10.6.7-MariaDB
I'm running on a Bitnami Wordpress stack
The question: What is causing this error?
I know it's a complex environment and many things could be at fault, but looking at the code I provided, is anything there that looks potentially guilty?
If the error that I have described is not clear enough, please bare with me as this is a very unique situation which I have never encountered, and I will do my best to make it clearer for you.
EDIT
Tim Morton raised some relevant topics in the comments, so I'll reply to them here to improve context for this question.
'Your first "fix" was to print a javascript command?'
I printed multiple JS commands (console.log) just to see at what point in the PHP script it crashed. When I ran it I noticed that the simple presence of these console.log commands, for some bizarre reason, fixed the crash itself.
'Then changed the syntax of your loop? This seems aimless.'
Yes, and yes it does seem aimless, but believe me it worked. That's why I'm dumbfounded, since it shouldn't.
'Is it printing all of the php-generated content and then failing some javascript?'
No, there is no Javascript here. The only JS was added later (console.log), as I explained, in order to see at what point the PHP crashed. It usually prints the PHP generated product-card.php (included by the loop) and at a random product, stops printing anything, even outside the loop.
'or is it failing in one particular part of the php loop?'
I'm pretty sure its in the PHP loop, but I have not been able to narrow it down.
'To diagnose, you could use try/catch and error_log() to help narrow it down to what is actually failing.'
Will do! The issue is, simply adding a try/catch will probably 'fix it' since as I stated earlier, random changes to the code seem to 'fix' the issue temporarily.
'Does the same record fail every time (hint, it could be the next record that's actually failing)'
So far it seems random. I've tried modifying the inventory record to place different products at different orders. This sometimes works, sometimes it doesn't. So far no pattern emerged.
UPDATE
So far, I've noticed two types of crashes. One of them it prints out halfway thru on a product-card.php iteration, then crashes (so it doesn't even get to the other iterations). On one of these cases, it crashed at only the second iteration.
On this specific case I've been able to see the front end code thru Chrome dev tools, and I noticed that it crashed right here, at the product-card.php
<a href="https://some-link.com/something/
As you can see, it crashed right after the echo, as it didn't even put the finishing quote and '>'.
On the other type of crash, it'd crash at a random iteration too, only the last iteration it'd finish rendering whatever card it was on and then crash, instead of crashing halfway thru.
I saw people commenting that I should just update or modify my PHP installation and be done with it, and to be honest I may do that since this is happening in prod, but this question is aimed at why this is happening.
What does contains $prdLink ?
What does contains $prdImg ?
What does contains $prdTitle ?
Are those variables correct sanitized ?
Does contains chars like ", ', > or anything that could ruins your dom ?
PS. If does, I'm afraid you have bigger problem, a security problem (XSS, etc).
After a very exhaustive wild-goose chase, I've come to the conclusion to the (likely) root cause of the issue:
Too many errors and warnings being logged onto the apache2/error.log file.
Seriously, it was like hundreds of warning logs per second, the file was several GBs large. I don't know exactly why it caused this behaviour, but turning off the logging for everything but critical errors seemed to solve the issue AFAIK (we didn't do anything else, it's AFAIK because we can't be 100% sure that this completely stopped for all our users).
Maybe it was a problem with the exception handler itself, as previously suggested. Maybe it were just too many exceptions to handle, maybe PHP or Apache were overwhelmed with so many logs. We'll never know.
Thank you for everyone who helped, commented and answered, definetely pointed me into the right direction. I were so desperate that I even bountied this, I think. Hopefully this will help another clueless developer out there.
I don't know if that's a typo made on this post or you copy pasted it but
<a href="https://some-link.com/something/ notice you are missing a " (sorry to not comment but not enough karma)
I have found that one common reason for the error is an exception being thrown from within an exception handler. I'm quite sure this doesn't happen in the application I'm trying to debug... But I've put all the initialization processing lines at the top of index.php in a try/catch.*
It can apparently also happen because some things cannot be serialized to be stored in a session. At most this application stores arrays into the session (quite a bit), but I'm confident that it doesn't store anything too out of the ordinary in it.
Someone commented that it happened to them because their primary key needed to be CHAR(32) instead of INT(11). The PK's in this app are all INTs.
Other suggestions are that it could be a problem with PHP 5.3.3 fixed in 5.3.6, full disk, and a need to typecast a SimpleXML value. We do happen to be running PHP 5.3.3, but upgrading would have to be a last resort in this case. It hasn't always been doing this.
UPDATE/NOTE: I actually can't reproduce the error myself, only see it happening in the logs, see below paragraph for where I believe the error is happening...
* From the error logs, it seems likely that at least one place it is happening is index.php. I am deducing this only because it is indicated in some entries by a referring URL. The try/catch code is currently only around the "top" initialization portion of the script, below that is mostly the HTML output. There is some PHP code in the output (pretty straightforward stuff though), so I may need to test that. Here is the catch part, which is not producing any output in the logs:
} catch (Exception $e) {
error_log(get_class($e)." thrown. Message: ".$e->getMessage(). " in " . $e->getFile() . " on line ".$e->getLine());
error_log('Exception trace stack: ' . print_r($e->getTrace(),1));
}
Would really appreciate any tips on this!
EDIT: PHP is running as an Apache module (Server API: Apache 2.0 Handler). I don't think there are any PHP accelerators in use, but it could just be that I don't know how to tell. None of the ones listed on Wikipedia are in phpinfo().
As far as I can tell the MPM is prefork. This is the first I'd ever looked into the MPM:
# ./httpd -l
Compiled in modules:
core.c
prefork.c
http_core.c
mod_so.c
The problem
In short you have a exception thrown somewhere, you have no idea where and up until now you could not reproduce the error: It only happens for some people, but not for you. You know that it happens for other people, because you see that in the error logs.
Reproduce the problem
Since you have already eliminated the common reasons you will need to reproduce the error. If you know which parameter will cause the error it should be easy to locate the error.
Most likely it is enough if you know all the POST/GET parameters.
If you can't reproduce with just these, you need to know additional request headers. Such as user agent, accept-encoding,...
If you still can't reproduce, then it becomes very difficult: The error may depend on a state (a session), the current time, the source ip address or the like.
The custom log method
Let's start simple: To get all parameters you can write in the very beginning of the affected php file something like:
file_put_contents("/path/to/some/custom_error_log", date()."\n".print_r(get_defined_vars(), true), FILE_APPEND | LOCK_EX);
Don't forget that the custom_error_log file must be writable to your php application. Then, when the error occurs in the error log, find the corresponding lines in your custom_error_log file. Hopefully there are not to many requests per second so that you can still identify the request. Maybe some additional parameters in the error log like source ip can help you identify the request (if your error log shows that).
From that data, reconstruct a request with the same POST/GET parameters.
The tcpdump method
The next option that is very simple as well, but requires you to have root-access on your target machine is to install tcpflow. Then create a folder, cd into that folder and simply execute (as root) tcpflow "port 80". The option (port 80) is a pcap filter expression. To see all you can do with that, see man pcap-filter. There is a lot what these filter expressions can do.
Now tcpflow will record all tcp connections on port 80, reconstruct the full data exchange by combining the packages belonging to one connection and dump this data to a file, creating two new files per connection, one for incoming data and one for outgoing data. Now find the files for a connection that caused an error, again based on the timestamp in your error log and by the last modified timestamp of the files. Then you get the full http request headers. You can now reconstruct the HTTP request completely, including setting the same accept-encoding, user-agent, etc. You can even pipe the request directly into netcat, replaying the exact request. Beware though that some arguments like a sessionid might be in your way. If php discovers that a session is expired you may just get a redirect to a login or something else that is unexpected. You may need to exchange things like the session id.
Mocking more things
If none of this helps and you can't reproduce the error on your machine, then you can try to mock everything that is hard to mock. For example the source ip adress. This might make some stunts necessary, but it is possible: You can connect to your server using ssh with the "-w" option, creating a tunnel interface. Then assign the offending ip adress to your own machine and set routes (route add host ) rules to use the tunnel for the specific ip. If you can cable the two computers directly together then you can even do it without the tunnel.
Don't foget to mock the session which should be esiest. You can read all session variables using the method with print_r(get_defined_vars()). Then you need to create a session with exactly the same variables.
Ask the user
Another option would be actually ask the user what he was doing. Maybe you can follow the same steps as he and can reproduce.
If none of this helps
If none of that helps... well... Then it gets seriously difficult. The IP-thing is already highly unlikely. It could be a GEO-IP library that causes the error on IPs from a specific region, but these are all rather unlikely things. If none of the above helped you to reproduce the problem, then you probably just did not find the correct request in all the data generated by the custom_log_file-call / tcpflow. Try to increase your chances by getting a more accurate timestamp. You can use microtime() in php as a replacement for date(). Check your webserver, if you can get something more accurate than seconds in your error log. Write your own implementation of "tail", that gives you a more accurate timestamp,... Reduce the load on the system, so that you don't have to choose from that much data (try another time of day, load of users to different servers,...)
circle the problem once you can reproduce
Now once you can reproduce it should be a walk in the park to find the actual cause. You can find the parameter that causes the error by trial and error or by comparing it to other requests that caused an error, too, looking for similarities. And then you can see what this parameter does, which libraries access it, etc. You can disable every component one by one that uses the parameter until you can't reproduce anymore. Then you got your component and can dive into the problem deeper.
Tell us what you found. I am curious ;-).
I had such an error, too. Found out that I returned a sql object in my session class (that was used by the session_handler) instead of returning nothing or at least not the sql object. First look into your _write and _read methods, if you too return some incorrect stuff.
Notice: ... Unknown on line 0 - How to find correct line, it's NOT "line 0"
I realize this question has already been answered, but I'll add this since it may help someone:
I managed to (unintentionally) produce errors without a stack frame from a function which used its own error handler to maintain control of execution while calling a potentially "dangerous" function, like this:
// Assume the function my_error_handler() has been defined to convert any
// PHP Errors, Warnings, or Notices into Exceptions.
function foo() {
// maintain control if danger() crashes outright:
set_error_handler('my_error_handler');
try {
// Do some stuff.
$r = danger();
} catch (Exception $e) {
$r = 'Bad Stuff, Man!';
}
restore error_handler();
return $r;
}
The "untraceable failure" would happen at the end of the program execution if the logic in "Do some stuff" returned from foo() directly, bypassing the call to restore_error_handler(). What I took away from the experience is this:
PHP maintains a stack of error handlers which gets deeper/taller with each call to set_error_handler().
Bad Stuff can happen if you push error handlers onto the stack and don't clean up after yourself before the program exits "normally".
This was a tough bug to isolate - I basically narrowed the problem down to the above function and then stared at it until my eyes bled.
So how would I have tracked this down, knowing what I know now? Since I don't know of any way to inspect the PHP error handler "stack" directly, I'm thinking it might make sense to use a Singleton object to encapsulate all set/restore operations for PHP error handlers. At least then it would be possible to inspect the state of the Singleton before exiting the program normally, and if "dangling" error handlers are detected to generate a sensible failure/warning message before PHP freaks out.
Instead of wrapping code in a try/catch block, what happens when you register an exception handler? Clearly your try/catch block is not catching the exception, thus resulting in the errors logged to Apache. By registering a handler, you can be sure any uncaught exception is handled.
Also, if you're using namespaces in your application, make sure you write \Exception in your catch block (or include the Exception class via a use statement).
This may be a little late but one issue I discovered when moving a site from a local to a remote server. I was using Concrete5 cms had developed my site locally(windows 8 in xampp) and then uploaded to a remote server running Cent 0S
Windows mysql by default is case insensitive and created a lower case database. Once this was uploaded to the remote server I received the "Exception thrown without a stack frame in Unknown on line 0?"
I then corrected the database tables case and my site started working again.
For us, this error was due to inadvertently serializing SimpleXML objects.
If you are using SimpleXML objects with 5.3.3, make sure you are are casting the node values to whatever you need (e.g. string) if you are serializing the values in the session.
Before:
$token = $response->Token->Value;
/* token saved in session, results in line 0 error */
After:
$token = (string) $response->Token->Value;
/* token saved in session, no error */
I had completely the same error. A very spacial case: if you connect an unnamed function (closure) hook to an object instance's hook point. After that you try to serialize this object.
I had the same error after filling the Illuminate Eloquent model's Fillable property incorrectly. Note the last 3 elements of the array, one is missing a coma.
protected $fillable = [
'budget',
'routestatus' ,
'userroutenumber'
'totalmovingseconds',
'totalidleseconds'
];
I had the same error, it appeared upgrading server from centos 5 to centos 6 and downgrading PHP from 5.4 to 5.3. Actual issue was PHP apc, not configured properly. Check your APC. I was using Symfony2, so you might find some help at Symfony Unable to allocate memory for pool
one simple way to produce this error is an old server with register_globals = On. then you only need two lines of code:
<?php
$_SESSION["my_var"] = "string";
$my_var = new MyClass(); //could be any class, i guess
?>
as soon as you reload this page once, you'll get the Exception thrown without a stack frame in Unknown on line 0 - error. seems like there is a conflict between the instance of the class and the (session) variable.
at least this is how i got this annoying error which is so hard to debug.
This problem occurred for me when I changed the namespace on a few Symfony bundles. Deleting the files in the the symfony cache directory fixed the issue.
Likely you have a corrupt/inconsistent table in the database. Try dumping the database. If you get a error that's the time. Repair that table and the issue should go away.
It is for this reason why clean install works. The clean install is just that clean.
mysqlcheck should work but if it does not show and issue still do above.
When using Magentos log facility Mage::log() it sometimes causes a white screen. No error messages are outputted either to the screen or any of the log files (var/log/system.log, var/log/exception.log )
This seems to happen only when I'm trying to log a very large object. for example when I'm trying this
Mage::log(Mage::helper('catalog/category')->getStoreCategories());
inside a block controller it causes a white screen.
the same happens when I'm trying to log the current product in app/design/frontend/enterprise/default/template/catalog/product/view/media.phtml
using
Mage::log($_product);
Usually Mage::log() works fine and writes everything to the system.log file.
I was wondering if this has happened to anybody else or if anybody has an idea about why this is happening?
Mage::log works a lot like print_r, private and protected values are printed too which includes extensive resource details. You can avoid these by using the purpose made Varien_Object::debug method.
Mage::log($_product->debug());
debug is also preferred because it detects recursion which not all versions of PHP do.
I guess it happens to everyone.
Try not to log large objects.
In case you need I would advice you to use die.
for example like this
$object = ...;
die($object);
or
die('pre html tag'.print_r($object,true).'pre html tag');
I installed phpMyAdmin on my site and it works. But when I mistype a query it does not show the mysql error message only the error code.
1064 -
I expect the following:
1064 - You have and error in your blah blah...
Without an error message it's difficult to know what's wrong.
In my php scripts I'm able to get the error message via mysql_error(). But myAdmin shows nothing.
I googled a lot but I didn't find anything useful.
How can I make it show the error messages?
Any ideas?
Judging by the fact that you get "#1064 -" as output, I can find only two places in the phpMyAdmin 3.3.9.2 source where the error could be occurring. The first is in the call to mysql_error or mysqli_error, depending on which backend your installation is using. I see you said that mysql_error works fine; if the phpMyAdmin information page you get when first logging in indicates that mysqli is being used, you might want to check that too.
But if mysql_error works, it seems more likely that the problem is in phpMyAdmin's character set conversion function PMA_DBI_convert_message in libraries/database_interface.lib.php. You can confirm this easily enough by inserting return $message; at the very top of that function, bypassing everything else in there. If that makes it (more or less) work, you'd probably want to determine what $server_language and $GLOBALS['charset'] are getting set to; see if the conversion is using iconv, recode_string, libiconv, or mb_convert_encoding; and then try to work out why whichever of those is failing to convert the error message properly.
Probably, Server cannot correctly access LOCALE settings. It happens on chroot-ed / chjail-ed environments or poor configuration.
Based on #Anomie answer, I made a workaround.
For phpmyadmin 4.4.3 change the Fallback setting in file libraries/DatabaseInterface.class.php
/* Fallback to CP1252 if we can not detect */
$encoding = 'UTF-8';
For some older versions, edit file libraries/database_interface.lib.php and set
array $encodings => 'english' value to UTF-8 (~line 273),
'english' => 'UTF-8', //'latin1',
Did you see :
$cfg['Error_Handler']['display']
boolean
Whether to display errors from PHP or not.
$cfg['Error_Handler']['gather']
boolean
Whether to gather errors from PHP or not.
In the docs ?
Had the same problem, which was solved by disabling the FireFox add-on uBlock (version: Origin 1.25.2) in my browser for phpmyadmin.
I looked at the messages I could find, but didn't find an answer that appears to help. I have a routine that calls debug_backtrace() and then cycles through the elements, outputting them in a nice format for my log. This works fine in most cases.
In some calls, the system just hangs. Assuming the following:
$curStack = debug_backtrace();
foreach ($curStack as $myStackLevel) {
$test = gettype($myStackLevel);
// code to write out contents of $myStackLevel
// Log that we are getting the next item
}
// Log that the foreach is done
In some cases, PHP just dies - I can see the log that it processed the current item, but it crashes on the foreach line (or at least before I can programatically see the contects of the next $myStackLevel.
In one message here, I saw something about recursive calls and using serialize, but I can't use serialize (I use PDO and had the message "You cannot serialize or unserialize PDO instances") So that's out.
The funny thing is that, if it crashes, the PHP error system still provides a complete dump of the stack.... (I found this out when I tried to use serialize).
Any help is appreciated....
Thanks,
JustMeToo
Are you trying to output the contents of the object elements? It's likely that you have a recursive object graph that causes the PHP process to either overflow the stack or take too long to run.