Re: Benchmarked tcpserver dlopen() -> qmail_smtpd() VS tcpserver --> fork() --> exec qmail-smtpd
Manvendra Bhangui <[email protected]> Wed, 5 Apr 2017 01:36:10 +0530
| Newsgroups | gmane.mail.qmail.general |
|---|---|
| Message-ID | <CAOqj+1PoJP2B7ZdZFkqFj9=w3bTtiL27rJ9cLgwKovp3D0=iOw@mail.gmail.com> |
On 5 April 2017 at 00:39, Erwin Hoffmann <[email protected]> wrote: > Absolutely ACK. And -- according to your list of control files -- at least some of them can be replaced by environment variables and can be merged into one control file (badmail*). This is the way Spamcontrol did it and s/qmail does it. That's how indimail does it too :). Environment variable BADMAILFROM and BLACKHOLEDSENDERS. In addition, it looks at the file extension. If it is .cdb, it uses cdb search. If it has .sql extension, then it connects to mysql as per database name, tablename, user, socket, etc stored in badmail.sql file. So no issues here. > PS: Apart from that: a 25K badmail file is ridiculous. Something is wrong with your mail architecture. > No. I don't use a 25 Mib badmail file. That example was to make apparent the penalty imposed in the current architecture where every invocation of qmail-smtpd reads this file. I just load the badmail file in tcpserver and the data is available to each and every child without the need to again open it. The disadvantage - If the file changes, I have to send tcpserver SIGHUP. Even for small control files, I have been able to see small performance improvement by loading the control files just once. David who replied in an earlier post suggested using inotify and also suggested using a control file server using UNIX Domain sockets. One of these days I am gonna use TCP IP socket. With so many relay servers, one will have to maintain this control file at just one location and also cache the file locally in case the control file server is not available. But that's for another day. My dlopen() architecture was completed months ago but I did not succeed in making the tcpserver symbols private to just the tcpserver executable. If the symbols can be private how can that be less secure then using exec() ? So yesterday I discovered dlmopen() which allows you to create a private namespace but I have been struggling to make it work with tcpserver. Had a painful session completed few mins ago with gdb. The moment I use dlmopen(), tcpserver goes at the top, consuming 100% cpu. gdb showed that it never returned from the function prot_gid() defined in prot.c. I figured out that due to NPTL, Native Posix Thread Library, setgroups, setgid, setuid, etc are all wrappers which are supposed to set the gid, uid of all threads in case of multi-threaded processes. The setgroups() and setgid() implementation on linux definitely has a bug. setgroups(), setgid() hang in all cases if dlmopen has been called. setuid() hangs only if it is passed int instead of uid_t. The original prot.c uses int instead of uid_t. Since tcpserver is not a multi-threaded application I have fixed the file prot.c in the ucsp-tcp-0.88 as following to bypass the NPTL wrappers in glibc. WIth this change, it is bliss/nirvana for me at the moment :) #include "hasshsgr.h" #include "prot.h" #include <unistd.h> #include <grp.h> #include <syscall.h> #define SYS_SETGROUPS(NGRUP,MYGIDSET) syscall(SYS_setgroups, NGRUP, MYGIDSET) #define SYS_SETGID(MYGID) syscall(SYS_setgid, MYGID) #define SYS_SETUID(MYUID) syscall(SYS_setuid, MYUID) int prot_gid(gid_t gid) { #ifdef HASSHORTSETGROUPS short x[2]; x[0] = gid; x[1] = 73; /*- catch errors */ if (SYS_SETGROUPS(1, x) == -1) return -1; #else if (SYS_SETGROUPS(1, &gid) == -1) return -1; #endif return SYS_SETGID(gid); /*- _should_ be redundant, but on some systems it isn't */ } int prot_uid(uid_t uid) { return SYS_SETUID(uid); } -- Regards Manvendra - http://www.indimail.org GPG Pub Key http://pgp.mit.edu:11371/pks/lookup?op=get&search=0xC7CBC760014D250C