1
0
mirror of https://git.FreeBSD.org/ports.git synced 2025-01-08 06:48:28 +00:00
freebsd-ports/mail/dbmail/files/patch-0007-Disconnect-IMAP-clients-if-only-few-free-FDs-left
Muhammad Moinur Rahman 9eff14e488 mail/dbmail: adopt latest fixes from git:
- login_disabled option before starttls for pop3
- fix compiler warnings for GCC5
- Fix IMAP mailbox maintanence
- prevent assertion in p_string_erase
- improve crypt authentication, also don't segfault when spasswd is empty
- simplify log_query_time duration logic
- Disconnect IMAP clients if only few free FDs left
- Add primary key constraint to dbmail_authlog
- Rework temporary connection failures
- Give sensible default for retry 120s
- Add retries for binding and searching
- Bump search timeout to 60s
- Increase ldap timeout to 600s 10 mins
- Refactor deprecated functions
- Get timeout from config
- Remove redundant event_assign
- Remove deprecated non functioning g_mem_profile
- Add definition for authldap_free
- Revert inadvertent event_assign removal
- Reduce failed LDAP connection for search to error
- Update LDAP to non deprecated search
- Clear the ldap connection
- Update ldap deprecated unbind
- Fix typo
- Update to ldap_unbind_ext_s and remove redundant sigaction
- Rebalance commit rollback
- Ensure mailbox2dbmail is using Python 2
- Tidy mailbox2dbmail man page
- Update description of pid file location in server man page
- Boundaries fixups ordering of parts do not add newline on
- Prepend headers during delivery
- Allow for systems that don't use proc

PR:		210274
Submitted by:	fluffy
2017-02-24 21:15:52 +00:00

149 lines
4.1 KiB
Plaintext

From 6b7eccfec4f76b7d9d1f865caf741ff3214b5964 Mon Sep 17 00:00:00 2001
From: Pavlo Lavrenenko <santa.ssh@gmail.com>
Date: Thu, 2 Jun 2016 08:18:51 +0300
Subject: [PATCH 07/33] Disconnect IMAP clients if only few free FDs left (#37)
After network connection to DB server goes down the processing of IMAP session
stalls: DB connection pool becomes exhausted as active connections do not
close till TCP timeout kicks in (true at least for Oracle). While DBMail still
accepts incoming connections it quickly reaches the RLIMIT_NOFILE and becomes
unresponsive. Send BYE response if the number of opened FDs reaches the
RLIMIT_NOFILE value.
---
src/dbmail.h.in | 5 +++++
src/dm_misc.c | 20 ++++++++++++++++++++
src/dm_misc.h | 8 ++++++++
src/imap4.c | 23 ++++++++++++++++++++++-
4 files changed, 55 insertions(+), 1 deletion(-)
diff --git src/dbmail.h.in src/dbmail.h.in
index d826dc3..17215ef 100644
--- src/dbmail.h.in
+++ src/dbmail.h.in
@@ -69,12 +69,14 @@
#include <string.h>
#include <strings.h>
#include <sysexits.h>
+#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
+#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
@@ -252,6 +254,9 @@
/* input reading linelimit */
#define MAX_LINESIZE (64*1024)
+/* minumun number of free file descriptors required to run the daemon */
+#define FREE_DF_THRESHOLD 16
+
/* string length for query */
#define DEF_QUERYSIZE (32*1024)
#define DEF_FRAGSIZE 256
diff --git src/dm_misc.c src/dm_misc.c
index e27ef34..e795de1 100644
--- src/dm_misc.c
+++ src/dm_misc.c
@@ -104,6 +104,26 @@ int drop_privileges(char *newuser, char *newgroup)
return 0;
}
+int get_opened_fd_count(void)
+{
+ DIR* dir = NULL;
+ struct dirent* entry = NULL;
+ char buf[32];
+ int fd_count = 0;
+
+ snprintf(buf, 32, "/proc/%i/fd/", getpid());
+
+ dir = opendir(buf);
+ if (dir == NULL)
+ return -1;
+
+ while ((entry = readdir(dir)) != NULL)
+ fd_count++;
+ closedir(dir);
+
+ return fd_count - 2; /* exclude '.' and '..' entries */
+}
+
void create_unique_id(char *target, uint64_t message_idnr)
{
char md5_str[FIELDSIZE];
diff --git src/dm_misc.h src/dm_misc.h
index 9660dfa..b6cf24f 100644
--- src/dm_misc.h
+++ src/dm_misc.h
@@ -45,6 +45,14 @@ void g_string_maybe_shrink(GString *s);
int drop_privileges(char *newuser, char *newgroup);
/**
+ \brief get the number of opened files (requires /proc mounted)
+ \return
+ - -1 on error
+ - number of opened files
+*/
+int get_opened_fd_count(void);
+
+/**
* \brief create a unique id for a message (used for pop, stored per message)
* \param target target string. Length should be UID_SIZE
* \param message_idnr message_idnr of message
diff --git src/imap4.c src/imap4.c
index 0532f2e..e523edc 100644
--- src/imap4.c
+++ src/imap4.c
@@ -351,6 +351,12 @@ static void send_greeting(ImapSession *session)
dbmail_imap_session_set_state(session, CLIENTSTATE_NON_AUTHENTICATED);
}
+static void disconnect_user(ImapSession *session)
+{
+ imap_session_printf(session, "* BYE [Service unavailable.]\r\n");
+ imap_handle_abort(session);
+}
+
/*
* the default timeout callback */
@@ -601,6 +607,8 @@ int imap_handle_connection(client_sock *c)
{
ImapSession *session;
ClientBase_T *ci;
+ struct rlimit fd_limit;
+ int fd_count;
ci = client_init(c);
@@ -617,7 +625,20 @@ int imap_handle_connection(client_sock *c)
Capa_remove(session->capa, "LOGINDISABLED");
}
- send_greeting(session);
+ fd_count = get_opened_fd_count();
+ if (fd_count < 0 || getrlimit(RLIMIT_NPROC, &fd_limit) < 0) {
+ TRACE(TRACE_ERR,
+ "[%p] failed to retrieve fd limits, dropping client connection",
+ session);
+ disconnect_user(session);
+ } else if (fd_limit.rlim_cur - fd_count < FREE_DF_THRESHOLD) {
+ TRACE(TRACE_WARNING,
+ "[%p] fd count [%d], fd limit [%d], fd threshold [%d]: dropping client connection",
+ session, fd_count, fd_limit.rlim_cur, FREE_DF_THRESHOLD);
+ disconnect_user(session);
+ } else {
+ send_greeting(session);
+ }
reset_callbacks(session);
--
2.10.1 (Apple Git-78)