Build Alpine 2.23 on OpenBSD to Fix Hang When Sending Mail

Once again, I love the Alpine MUA. Simple and robust, it just works, and is much faster than a GUI mail client.

During a recent OpenBSD install (6.7) I ran into a issue where Alpine 2.21 from Ports (alpine-2.21p4) hangs when “Sending Mail.” Occasionally, but repeatably if you send a number of messages Alpine will hang when it gets to Sending Mail. I tried the usual fixes… I checked the “Sendmail Path” and the “SMTP Server (for sending)” settings in the config and tested that those were working. The code would suggest that Sendmail Path is used first. So if that is not working on your system then you want to remove that setting in the config (it’s down lower in the config for some reason, rather than up at the top) before setting your SMTP Server.

This was not the issue in my case, and unlikely your issue if you have smtpd configured and running. Sending via sendmail -t and the SMTP server on localhost worked fine most of the time… But then every few emails (sometimes as few as two, sometimes ten or more) Alpine would hang on Sending Mail and I would have to kill it with a kill -9.

For the curious (skip this unless you like code), this is the ktrace where it would hang every time. The last line is me killing it:

 53976 alpine   NAMI  "/tmp/pine_p43476"
 53976 alpine   RET   lstat -1 errno 2 No such file or directory
 53976 alpine   CALL  open(0x32ce7654b80,0xa01<O_WRONLY|O_CREAT|O_EXCL>,0600<S_IRUSR|S_IWUSR>)
 53976 alpine   NAMI  "/tmp/pine_p43476"
 53976 alpine   RET   open 6
 53976 alpine   CALL  close(6)
 53976 alpine   RET   close 0
 53976 alpine   CALL  pipe(0x7f7ffffc41b8)
 53976 alpine   STRU  int [2] { 6, 7 }
 53976 alpine   RET   pipe 0
 53976 alpine   CALL  sigaction(SIGCHLD,0x7f7ffffc3d28,0x7f7ffffc3d18)
 53976 alpine   STRU  struct sigaction { handler=0x32a0e994e70, mask=0<>, flags=0x2<SA_RESTART> }
 53976 alpine   STRU  struct sigaction { handler=0x32a0e994e70, mask=0<>, flags=0x2<SA_RESTART> }
 53976 alpine   RET   sigaction 0
 53976 alpine   CALL  futex(0x32cf9b38690,0x81<FUTEX_WAIT|FUTEX_PRIVATE_FLAG>,2,0,0)
 53976 alpine   RET   nanosleep 0
 53976 alpine   CALL  kbind(0x32c364e8868,24,0x400e0443c3a0c61)
 53976 alpine   RET   kbind 0
 53976 alpine   CALL  gettimeofday(0x32c364e8660,0)
 53976 alpine   STRU  struct timeval { 1598335368<"Aug 25 01:02:48 2020">.986756 }
 53976 alpine   RET   gettimeofday 0
 53976 alpine   CALL  futex(0x32cf9b38618,0x81<FUTEX_WAIT|FUTEX_PRIVATE_FLAG>,2,0,0)
 53976 alpine   PSIG  SIGKILL SIG_DFL

A backtrace in gdb showed it was called from _rthread_mutex_timedlock. However, I did not research it further. I am not up on debugging pthread programs, and gdb kept breaking constantly when changing threads.

The Fix

Anyway, I built and installed the latest Alpine 2.23 from the official source. I had to patch it with the patches from the ports collection, as well as with my own highly recommended patch to fix the “[Folder vulnerable – directory /var/mail must have 1777 protection]” issue on OpenBSD detailed here. Without the patch on that other page your mailbox may be subject to corruption. Check it out.

First download the latest source tarball from the official Alpine site. I like to do all this in $HOME/src/ but you can do this wherever you like. Also grab my complete patch (SHA256) which combines the OpenBSD Ports patches plus my Folder Vulnerable patch in one big patch file. (You might want to check the hash on the Alpine distro with the one posted on the Alpine site.)

wget http://alpine.x10host.com/alpine/release/src/alpine-2.23.tar.xz
wget https://sourceopen.com/alpine-2.23-openbsd-patch
wget https://sourceopen.com/alpine-2.23-openbsd-patch.sha256

Note this is an .xz compressed archive for some reason instead of the usual .gzip. So:

unxz alpine-2.23.tar.xz

Then expand the tar archive:

tar xf alpine-2.23.tar

Next we will apply the patch to the source code.

A little security note: Please take a look at the patch and make sure there is nothing untoward. I point this out only because applying random patches can possibly be dangerous. Rest assured, I am a nice guy and not trying to do anything bad, but you want to be in the habit of at least looking at the lines in the patch preceded by “+” to make sure there is nothing fishy going on. This works perfectly here. YMMV.

We first check the hash of the patch before applying it.

sha256 alpine-2.23-openbsd-patch

This should result in output like this (the hash should match exactly):

SHA256 alpine-2.23-openbsd-patch) = e7c6d44678030dd11e6e686da2d8997810408561bf51e461a0914cce6baa2791

Next we apply the patch from the directory one above the alpine-2.23 directory. So if you have /$HOME/src/alpine-2.23 then you should still be in the directory you downloaded to /$HOME/src/. This command and this patch will patch all the various files in the alpine-2.23 directory at once!

patch -p0 < alpine-2.23-openbsd-patch

This should result in a bunch of output from patch. Look over this and make sure all the “hunks” succeeded.

Next we configure and make, but we do not install. You could use make to install, but this will install all the other programs you likely don’t need like pico (use GNU nano instead) and pilot, etc. We will install manually below. It’s easy.

cd alpine-2.23
./configure
make

# Or you can do them both if you want to walk away while it build with:
./configure && make

This will build everything up, hopefully with no errors. It is possible there are prerequisite packages (dependencies) that need to be built or installed. In this case you might be easiest to first install the package for alpine, letting pkg_add install the dependencies, and then uninstall the alpine package without removing dependencies.

pkg_add alpine
#(let it install dependencies)
pkg_delete alpine
#(only deletes alpine by default and not dependencies)

After running this go back and run the ./configure and make again. Probably a good idea to do a make distclean first, in case any of the missing stuff was cached as missing.

make distclean
./configure && make

Now you can manually install just the alpine binary. Make sure you are in the alpine-2.23 directory and run:

doas install -o root -g bin -m 0755 -b alpine/alpine /usr/local/bin/alpine

The -b option will backup any existing alpine to /usr/local/bin/alpine.old. Be sure to delete this when you are sure you don’t need it any more. If you get an error about doas not being enabled then su to root and install it without the “doas” at the start of the line. (Or enable doas if you prefer. I don’t care for doas, and don’t use it.)

Now start up Alpine (just run “alpine”) and make sure you are seeing version 2.23 in the top banner. That’s it! This new update solved my issue of Alpine hanging on Sending Mail in OpenBSD. You should also now not have to worry about the whole Folder Vulnerable issue as well, as this patch is included.

Let me know in the comments how this worked for you.

This entry was posted in Uncategorized and tagged , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *