palant / opensmtpd-filters

Converting DMARC aggregate reports into human-readable HTML
MIT License
17 stars 2 forks source link

On OpenBSD the filters keep running after shutting down smtpd #4

Open wimstockman opened 3 days ago

wimstockman commented 3 days ago

Hi , I use your opensmtpd-filters dkimsign and dkimverify on my OpenBSD server , currently version 7.5. and noticed that when I do "rcctl stop smtpd" both filters don't stop and start using all of the CPU , they go wild. I tried your code also on my Linux Arch servers and there it works fine. So it's somekind of OpenBSD issue

I tried to attache signal handlers in your code but nothing worked. I finally resorted to changing the rc file for smtpd. and adding a pkill for the user _smtpd. This works maybe you can find a more gracefull way Thanks for the great work !

Here is my smtpd rc file:


#!/bin/ksh
#
# $OpenBSD: smtpd,v 1.8 2022/10/14 11:02:43 kn Exp $

daemon="/usr/sbin/smtpd"

. /etc/rc.d/rc.subr

rc_configtest() {
    # use rc_exec here since daemon_flags may contain arguments with spaces
    rc_exec "${daemon} -n ${daemon_flags}"
}
rc_stop() {
pkill -u _smtpd
}

rc_reload=NO

rc_cmd $1
palant commented 3 days ago

Actually, OpenSMTPD is supposed to manage its filters. It starts them and should shut them down as well. So this sounds like an OpenSMTPD issue to me.

It’s still strange that the filters use up CPU however. Presumably, there is no OpenSMTPD process around to provide them with input any more, reading from stdin should result in a “Broken pipe” error. But it sounds like the self._stdin.readline() call returns an empty string instead.

palant commented 3 days ago

According to documentation, readline() will in fact return an empty string on a stream past EOF. Could you try changing function recv() in opensmtpd.py? Replace return self._stdin.readline().rstrip('\r\n') by the following:

        line = self._stdin.readline()
        if line == '':
            raise Exception('No more input')
        else:
            return line.rstrip('\r\n')
wimstockman commented 3 days ago

Hi , Thx for your quick reply. I tried your solution but no luck it still does the same. I think it is indeed an OpenSMTPD problem in OpenBSD because if I just run the dkimsign in the shell. It does receive the SIGTERM signal and gracefully stops. Kind regards, Wim

palant commented 3 days ago

I can reproduce a problem on Linux by running:

echo test | dkimverify 

I fixed it: https://github.com/palant/opensmtpd-filters/commit/eedfd53c0302a6cb29c06dbdb8785bc9e006482c. This isn’t necessarily the problem you are seeing on OpenBSD, I don’t see any other way this code could get into a tight loop however.