Nasty qmail-remote hangs forever bug

I am very happy with my current mail setup. But a nasty bug popped up out of nowhere and i can’t trace it…. Some qmail-remote processes, in some circunstances yet to determine, just hang-up forever eating all the available CPU. The qmail-remote is the piece of Qmail that takes care of message delivery to recipients at a remote host.

When this happens, the stuck process doesn’t conform to the timeoutremote control and stays active forever. The truss command (FreeBSD equivalent to strace) doesn’t show any activity and neither appears to be related network activity… it looks like some kind of race condition.

For now i couldn’t really address the issue, to both lack of time and deep understanding about C and debugging with GDB, so i just mitigate the problem with a cron running a bash script to detect and kill the offending processes.

#!/usr/local/bin/bash

# limit in seconds
LIMIT_TIME=120
# limit in cpu
LIMIT_CPU=35


IFS=$'\n'

for line in `ps -xao pid,etime,command,%cpu | grep qmail-remote`; do

  pid=`echo $line | awk '{split($0,a," "); print a[1]}'`
  time=`echo $line | awk '{split($0,a," "); print a[2]}'`
  cpu=`echo $line | awk '{split($0,a," "); print a[5]}'`
  cpu=`echo "($cpu)/1+1" | bc`

  IFS=$':'
  time_parts=($time)

  if [ ${#time_parts[@]} -lt 3 ]; then
    elapsed=`echo ${time_parts[0]}*60 + ${time_parts[1]} | bc`
  else
    elapsed=`echo ${time_parts[0]}*3600 + ${time_parts[1]}*60 + ${time_parts[2]} | bc`
  fi

  if [ $elapsed -gt $LIMIT_TIME -a $cpu -gt $LIMIT_CPU ]; then
    kill -s 9 $pid
   fi

IFS=$'\n'
done

But i’m not really happy with this “solution”, and will be pursuing a real understanding and solution for this proble.

Some interesting links about other people with the same problem:

http://permalink.gmane.org/gmane.os.freebsd.stable/82760
http://copilotco.com/mail-archives/qmail.2002/msg08733.html

UPDATE and SOLUTION

All credits, to where credits are due.
To replicate this, you should catch an hanging qmail-remote with top. Then filter the offending qmail-remote pid trough ps to get full arguments list:

ps -wwaux | grep pid_number

You should get something like ‘qmail-remote mailserver from@email to@email’. With this information, and with top and truss you can invoke qmail-remote from the command line and get a nice qmail-remote hang…

truss /var/qmail/bin/qmail-remote mailserver my@email nonexisten@email < ./test

test is just a file with some bogus input to serve as the sending email, as qmail-remote expects a message in stdin. Just for the note, most of the hangs happens when talking to the Symantec Email Gateway software.

Now, with an updated ports tree, just recompile qmail, you can follow my guide (all good there). But, just issue make, no need to make install. Then move qmail-remote to /var/qmail/bin/ and set the right permissions (711) and ownership (root:qmail).

And voilá, if you repeat the test procedure, you will find that qmail-remote is not hanging anymore 🙂

FreeBSD FTP mount

Mount a FTP share in your local filesystem is really easy. And it just makes a FTP client feel like dark age software, with a local mount you can freely use your commands over the files and folders in the share.

First install curlftpfs

cd /usr/ports/sysutils/fusefs-curlftpfs/
make install clean

edit /etc/rc.conf and add

fusefs_enable="YES"

and fire it up (actually no daemon here, just a kernel module load), you can see it with kldstat command.

/usr/local/etc/rc.d/fusefs start

Now we can happily mount FTP shares to local filesystem with the curlftpfs command.

curlftpfs ftp://user:pass@ftp.myserver.com /my/local/mount/

If you don’t want the user/pass typed in the command, and probably you don’t because it can be a bad thing ™ (out in the wild waiting for a ps done by other users…), just setup a .netrc file in your home dir with

machine ftp.myserver.com
login myuser
password mypass

then connect without the user/pass like:

curlftpfs ftp://ftp.myserver.com /my/local/mount/

UPDATE

I had some problems with this with a server that was running flawlessly for over a year and it stalled, so i don’t recommend it for production environments, must also test the asynchronous option

My Qmail installation guide

A fresh Qmail installation on FreeBSD is something that i have to deal once a couple of years. It´s just one of those things that i could well live without, but the time will come again and usually i can’t remember of half of my previous installation…. this is my personal installation guide to do it faster and with less effort.

Why Qmail? Why FreeBSD? Well, if you come all the way into this dark corner of the Internet, you should know the answer to both… so moving on, this is a massive, uber-geek, fully comprehensive and detailed installation guide, so it takes time and some brain damage.

CAUTION: proceed at your own risk

Continue reading “My Qmail installation guide”

PHP Email validation function

My PHP email validation function nowadays is:

function isEmail($value, $network_validation = true) {

    // Create the syntactical validation regular expression
    // (broken in 2 lines for better readability)
    $regexp = "/^([_a-z0-9-]+)(\.[_a-z0-9-]+)*@".
              "([a-z0-9-]+)(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/i";

    // Validate the syntax
    if(preg_match($regexp, $value)) {
        if (! $network_validation)
            return true;
  	 
        $tmp = explode('@', $value);
        $username  = $tmp[0];
        $domaintld = $tmp[1];
 
        // Validate the domain
        if (getmxrr($domaintld, $mxrecords) || checkdnsrr($domaintld, 'A'))
            return true;
    }
    return false;
}

This is for my own reference, maybe this is all messed up, so use it at your own risk.