ze-filter  (ze-filter-0.8.0-develop-180218)
ze-resource.c
Go to the documentation of this file.
1 
2 /*
3  *
4  * ze-filter - Mail Server Filter for sendmail
5  *
6  * Copyright (c) 2001-2018 - Jose-Marcio Martins da Cruz
7  *
8  * Auteur : Jose Marcio Martins da Cruz
9  * jose.marcio.mc@gmail.org
10  *
11  * Historique :
12  * Creation : janvier 2002
13  *
14  * This program is free software, but with restricted license :
15  *
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * More details about ze-filter license can be found at ze-filter
22  * web site : http://foss.jose-marcio.org
23  */
24 
25 #include <ze-sys.h>
26 #include <libze.h>
27 #include "ze-filter.h"
28 
29 
30 /* ****************************************************************************
31  * *
32  * *
33  **************************************************************************** */
34 
35 #define FAST_FD_COUNT 1
36 #define CHECK_FD_WITH_POLL 0
37 
38 #define DT_CHECK 10
39 
40 #define ZE_FD_MAX -1
41 #define ZE_FD_DFL 0
42 
43 #define ZE_NOFILE 256
44 
45 static long fd_last = 0;
46 static long fd_open = 0;
47 static long fd_idle = 0;
48 
49 static rlim_t fd_max = 0;
50 
51 static rlim_t fd_soft = 0;
52 static rlim_t fd_hard = 0;
53 
54 static long fd_conf = ZE_FD_DFL;
55 static rlim_t fd_cur = 0;
56 
57 static pthread_mutex_t st_mutex = PTHREAD_MUTEX_INITIALIZER;
58 
59 #if HAVE_POLL
60 #define POLL_IN_USE (POLLIN | POLLOUT | POLLPRI | POLLHUP)
61 #endif
62 
63 /* ****************************************************************************
64  * *
65  * *
66  **************************************************************************** */
67 #if HAVE_FDWALK
68 static int
69 fdwalk_count(void *count, int fd)
70 {
71  int *n = (int *) count;
72 
73  (*n)++;
74  return 0;
75 }
76 #endif /* HAVE_FDWALK */
77 
78 int
80 {
81  int i = 0;
82  struct rlimit rlp;
83 
84  time_t now = time(NULL);
85 
86  long lsoft, lhard, nb_idle, nb_used;
87 
90 
91 #if HAVE_SETRLIMIT
92  if (fd_max == 0) {
93  if (getrlimit(RLIMIT_NOFILE, &rlp) == 0) {
94  fd_max = rlp.rlim_cur;
95  } else {
96  fd_max = sysconf(_SC_OPEN_MAX);
97  }
98  }
99 #endif
100 
101 #if 0 && HAVE_FDWALK
102  nb_used = nb_idle = 0;
103 
104  /*
105  * call fdwalk...
106  */
107  nb_used = 0;
108 
109  (void) fdwalk(fdwalk_count, &nb_used);
110 
111  /*
112  * fd_last ???????? - this is wrong
113  */
114  nb_idle = fd_last - nb_used;
115 
116 #else /* HAVE_FDWALK */
117 
118  if (fd_last + DT_CHECK > now)
119  return fd_open;
120 
121  nb_used = nb_idle = 0;
122  for (i = fd_max - 1; i >= 0; i--) {
123 #if CHECK_FD_WITH_POLL == 1
124  struct pollfd ufds;
125  int r;
126 #else
127  struct stat buf;
128 #endif
129 
130 #if FAST_FD_COUNT
131  if (nb_idle > lsoft)
132  break;
133 #endif
134 
135 #if CHECK_FD_WITH_POLL == 1
136  ufds.fd = i;
137  ufds.events = POLLIN | POLLOUT;
138  ufds.revents = 0;
139 
140  r = poll(&ufds, 1, 0);
141 
142  if ((r < 0) && (errno == EBADF)) {
143  nb_idle++;
144  continue;
145  }
146 
147  if (r < 0) {
148  continue;
149  }
150 
151  if ((r > 0) && ((ufds.revents & POLLNVAL) != 0)) {
152  nb_idle++;
153  continue;
154  }
155 
156  if (r >= 0) {
157  nb_used++;
158  continue;
159  }
160 #else
161  if (fstat(i, &buf) == 0)
162  nb_used++;
163  else
164  nb_idle++;
165 #endif
166  }
167 #endif /* HAVE_FDWALK */
168 
169  MUTEX_LOCK(&st_mutex);
170  fd_last = now;
171  fd_open = nb_used;
172  fd_idle = nb_idle;
173  MUTEX_UNLOCK(&st_mutex);
174 
175 #if 0
176  ZE_MessageInfo(10, " FD : open=[%d] idle=[%d] now=[%ld]", fd_open, fd_idle,
177  now % 17);
178 #endif
179 
180  return nb_used;
181 }
182 
183 /* ****************************************************************************
184  * *
185  * *
186  **************************************************************************** */
187 
188 int
190 {
191  long lsoft, lhard;
192  long nb_idle, nb_open;
193 
196 
198 
199  MUTEX_LOCK(&st_mutex);
200  nb_open = fd_open;
201  nb_idle = fd_idle;
202  MUTEX_UNLOCK(&st_mutex);
203 
204  if (fd_max == 0)
205  return FD_LEVEL_OK;
206 
207 #if 1
208  if (nb_idle < lhard) {
209  ZE_LogMsgWarning(0, "file descriptors being short... (hard limit) %ld/%ld",
210  (long) fd_open, (long) fd_max);
211  return FD_LEVEL_HI;
212  }
213  if (nb_idle < lsoft) {
214  ZE_LogMsgWarning(0, "file descriptors being short... (soft limit) %ld/%ld",
215  (long) fd_open, (long) fd_max);
216  return FD_LEVEL_SHORT;
217  }
218 #else
219  if (nb_open + lhard > fd_max) {
220  ZE_LogMsgWarning(0, "file descriptors being short... (hard limit) %ld/%ld",
221  (long) fd_open, (long) fd_max);
222  return FD_LEVEL_HI;
223  }
224 
225  if (nb_open + lsoft > fd_max) {
226  ZE_LogMsgWarning(0, "file descriptors being short... (soft limit) %ld/%ld",
227  (long) fd_open, (long) fd_max);
228  return FD_LEVEL_SHORT;
229  }
230 #endif
231 
232  return FD_LEVEL_OK;
233 }
234 
235 /* ****************************************************************************
236  * *
237  * *
238  **************************************************************************** */
239 int
241 {
242 #if HAVE_SETRLIMIT
243  struct rlimit rlp;
244  char *strlim = cf_get_str(CF_FILE_DESCRIPTORS);
245  long lsoft, lhard;
246 
249 
250  if (strlim != NULL)
251  ZE_MessageInfo(11, "CF_FILE_DESCRIPTORS = %s", strlim);
252 
253  if (getrlimit(RLIMIT_NOFILE, &rlp) == 0) {
254  if (fd_soft == 0)
255  fd_soft = rlp.rlim_cur;
256  if (fd_hard == 0)
257  fd_hard = rlp.rlim_max;
258  } else {
259  ZE_LogSysError("getrlimit(RLIMIT_NOFILES) error");
260  return 0;
261  }
262 
263  if (strlim != NULL) {
264  if (strcasecmp(strlim, "DEFAULT") == 0)
265  fd_conf = ZE_FD_DFL;
266  else {
267  if (strcasecmp(strlim, "MAX") == 0) {
268 #if 0
269  fd_conf = ZE_FD_MAX;
270 #else
271  fd_conf = fd_hard;
272 #endif
273  } else {
274  long n;
275 
276  n = zeStr2long(strlim, NULL, ZE_FD_DFL);
277  if (errno == ERANGE || errno == EINVAL || n <= 0 || n > fd_hard)
278  n = ZE_FD_DFL;
279  fd_conf = n;
280  }
281  }
282  }
283 
284  if (fd_conf > fd_hard) {
285  ZE_MessageInfo(0, "Can't set file descriptor limit greater than %ld",
286  (long) fd_hard);
287  fd_conf = fd_hard;
288  }
289 
290  if ((fd_conf > 1) && (fd_conf < ZE_NOFILE)) {
291  fd_conf = ZE_NOFILE;
292  }
293 
294  switch (fd_conf) {
295  case ZE_FD_DFL:
296  fd_cur = fd_soft;
297  break;
298  case ZE_FD_MAX:
299  fd_cur = fd_hard;
300  break;
301  default:
302  fd_cur = (fd_conf >= ZE_NOFILE ? fd_conf : ZE_NOFILE);
303  break;
304  }
305 
306  ZE_MessageInfo(11, "Will set file descriptor limit to %ld [%ld,%ld]",
307  (long) fd_cur, (long) fd_soft, (long) fd_hard);
308 
309  if ((cf_get_int(CF_USE_SELECT_LIMIT) == OPT_YES) && (fd_cur > FD_SETSIZE)) {
310  ZE_MessageInfo(11,
311  "May not set file descriptor limit to more than FD_SETSIZE");
312  fd_cur = FD_SETSIZE;
313  }
314 
315  rlp.rlim_cur = fd_cur;
316  if (setrlimit(RLIMIT_NOFILE, &rlp) != 0) {
317  ZE_LogSysError("setrlimit(RLIMIT_NOFILE) error");
318  } else
319  ZE_MessageInfo(11, "RLIMIT_NOFILE set to %ld files", (long) rlp.rlim_cur);
320 
321  ZE_MessageInfo(9,
322  "File descriptors thresholds set to : soft=[%ld] - hard=[%ld]",
323  (long) (fd_cur - lsoft), (long) (fd_cur - lhard));
324 #endif
325 
326  return 0;
327 }
328 
329 /* ****************************************************************************
330  * *
331  * *
332  **************************************************************************** */
333 bool
335  bool enable;
336 {
337 #if HAVE_SETRLIMIT
338 #if 0
339  return TRUE;
340 #else
341  struct rlimit rlp;
342 
343  if (getrlimit(RLIMIT_CORE, &rlp) == 0) {
344  rlp.rlim_cur = (enable ? 32000000 : 0);
345 
346  if (setrlimit(RLIMIT_CORE, &rlp) != 0) {
347  ZE_LogSysError("setrlimit(RLIMIT_CORE) error");
348  return FALSE;
349  } else
350  ZE_MessageInfo(9, "RLIMIT_CORE set to %ld bytes", (long) rlp.rlim_cur);
351  } else {
352  ZE_LogSysError("getrlimit(RLIMIT_CORE) error");
353  return FALSE;
354  }
355 
356  return TRUE;
357 #endif
358 #else
359  return TRUE;
360 #endif
361 }
362 
363 
364 /* ****************************************************************************
365  * *
366  * *
367  **************************************************************************** */
368 bool
370 {
371 #if 0
372  struct rusage usage;
373  int r;
374 
375  ZE_MessageInfo(9, "Checking rusage...");
376  memset(&usage, 0, sizeof (usage));
377  r = getrusage(RUSAGE_SELF, &usage);
378  if (r == 0) {
379  long ru_maxrss; /* maximum resident set size */
380  long ru_ixrss; /* integral shared memory size */
381  long ru_idrss; /* integral unshared data size */
382  long ru_isrss; /* integral unshared stack size */
383 
384  ru_maxrss = usage.ru_maxrss;
385  ru_ixrss = usage.ru_ixrss;
386  ru_idrss = usage.ru_idrss;
387  ru_isrss = usage.ru_isrss;
388 
389  ZE_MessageInfo(9, "* RESOURCE CHECK : ru_maxrss = %10ld", ru_maxrss);
390  ZE_MessageInfo(9, "* RESOURCE CHECK : ru_ixrss = %10ld", ru_ixrss);
391  ZE_MessageInfo(9, "* RESOURCE CHECK : ru_idrss = %10ld", ru_idrss);
392  ZE_MessageInfo(9, "* RESOURCE CHECK : ru_isrss = %10ld", ru_isrss);
393  }
394 #endif
395 
396  return TRUE;
397 }
int count_file_descriptors()
Definition: ze-resource.c:79
#define CF_FILE_DESCRIPTORS
Definition: cfh-defs.h:39
bool enable_coredump(bool enable)
Definition: ze-resource.c:334
#define MUTEX_UNLOCK(mutex)
Definition: macros.h:101
bool check_rusage()
Definition: ze-resource.c:369
#define DT_CHECK
Definition: ze-resource.c:38
#define MUTEX_LOCK(mutex)
Definition: macros.h:93
#define FD_LEVEL_HI
Definition: ze-resource.h:34
#define FALSE
Definition: macros.h:160
#define OPT_YES
Definition: ze-cf.h:45
#define ZE_NOFILE
Definition: ze-resource.c:43
int cf_get_int(int id)
Definition: ze-cf.c:803
long zeStr2long(char *s, int *error, long dval)
Definition: zeStrConvert.c:35
#define CF_USE_SELECT_LIMIT
Definition: cfh-defs.h:42
#define FD_LEVEL_SHORT
Definition: ze-resource.h:33
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
#define FD_LEVEL_OK
Definition: ze-resource.h:32
#define TRUE
Definition: macros.h:157
int check_file_descriptors()
Definition: ze-resource.c:189
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
#define CF_FD_FREE_HARD_LIMIT
Definition: cfh-defs.h:41
#define ZE_FD_MAX
Definition: ze-resource.c:40
char * cf_get_str(int id)
Definition: ze-cf.c:854
#define ZE_LogMsgWarning(level,...)
Definition: zeSyslog.h:112
#define ZE_FD_DFL
Definition: ze-resource.c:41
#define CF_FD_FREE_SOFT_LIMIT
Definition: cfh-defs.h:40
int setup_file_descriptors()
Definition: ze-resource.c:240