I recently encountered a very frustrating problem with aMember (as if I haven’t encountered enough annoying problems with it already).
A customer said that they couldn’t log in. Each time they tried to log in, they would get the following error message in their browser:
MYSQL ERROR: MySQL server has gone away in query: INSERT INTO amember_access_log (member_id, remote_addr, url, referrer) VALUES (ID, 'IP_ADDRESS', '/member/member.php', 'URL')
After scratching my head a bit, I delved into the aMember code and found the problem in the plugins/db/mysql/mysql.inc.php
file which is where the log_access
and log_remote_access
functions are located. Both of these functions make use of the gethostbyaddr
PHP function. While this is a handy function, it should never be used in time-sensitive code (such as code that is run as part of a website; such as exactly how aMember uses this function).
The reason is that this function provides no reasonable timeout control, so if the function takes forever to return something, your code has halted until it finishes. In this instance, the visitor had a remote IP that just could not be reversed. This caused the gethostbyaddr
function to halt the aMember code for 20 seconds until it finally failed and returned the original IP address. While waiting for this function to return, the MySQL server naturally got tired of waiting and did other things, so when the code finally tried to keep running, everything quickly fell apart.
So ends the theory, time for a fix.
The lines of code that have the gethostbyaddr
calls aren’t necessary by any means, so they can be commented out completely. The lines to be commented out are 1605, 1606, 1617, and 1618. Such as the following:
1605 and 1606:
// if (preg_match('/proxy\.aol\.com$/', gethostbyaddr($REMOTE_ADDR)))
// return;
1617 and 1618:
// if (preg_match('/proxy\.aol\.com$/', gethostbyaddr($ip)))
// return;
I would show more code to give better context, but since aMember has a proprietary license, I won’t.
Note that there are more instances of gethostbyaddr
in aMember. The aMember devs are kind enough to put the other gethostbyaddr
calls in the PaySbuy, NETbilling, ccbill, and WorldPay payment processing plugins. No worries, this problem can only be found in the payment processing code, what could possibly go wrong?
The specific files that have these calls are:
plugins/payment/paysbuy/ipn.php
plugins/payment/netbilling_cc/netbilling_cc.inc.php
plugins/payment/ccbill/ipn.php
plugins/payment/worldpay/ipn.php
Did I help you?
You can set the timeout option n resolv.conf to a small value to avoid such problems. Usually if you don’t get an answer in 2 seconds you won’t get an answer. It’s not 1995. We often set the timeout to 1 second.
While that is a possible option, making such a modification would require root privileges which are not always available. In addition, we have moved on since 1995, but I still see slow DNS resolvers from time to time.