ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/fdlist.c
(Generate patch)

Comparing ircd-hybrid/trunk/src/fdlist.c (file contents):
Revision 1618 by michael, Tue Oct 30 21:04:38 2012 UTC vs.
Revision 9101 by michael, Wed Jan 1 09:58:45 2020 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  fdlist.c: Maintains a list of file descriptors.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2020 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 16 | Line 15
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18 < *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 > *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file fdlist.c
23 > * \brief Maintains a list of file descriptors.
24 > * \version $Id$
25   */
26  
27   #include "stdinc.h"
28   #include "fdlist.h"
27 #include "client.h"  /* struct Client */
28 #include "event.h"
29 #include "ircd.h"    /* GlobalSetOptions */
29   #include "irc_string.h"
30   #include "s_bsd.h"   /* comm_setselect */
32 #include "conf.h"  /* ServerInfo */
33 #include "send.h"
31   #include "memory.h"
32 < #include "numeric.h"
33 < #include "s_misc.h"
37 < #include "irc_res.h"
32 > #include "misc.h"
33 >
34  
35 < fde_t *fd_hash[FD_HASH_SIZE];
40 < fde_t *fd_next_in_loop = NULL;
35 > fde_t *fd_table;
36   int number_fd = LEAKED_FDS;
37   int hard_fdlimit = 0;
38 < struct Callback *fdlimit_cb = NULL;
44 <
45 < static void *
46 < changing_fdlimit(va_list args)
47 < {
48 <  int old_fdlimit = hard_fdlimit;
49 <
50 <  hard_fdlimit = va_arg(args, int);
38 > int highest_fd = -1;
39  
52  if (ServerInfo.max_clients > (unsigned int)MAXCLIENTS_MAX)
53  {
54    if (old_fdlimit != 0)
55      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
56        "HARD_FDLIMIT changed to %d, adjusting MAXCLIENTS to %d",
57        hard_fdlimit, MAXCLIENTS_MAX);
58
59    ServerInfo.max_clients = MAXCLIENTS_MAX;
60  }
61
62  return NULL;
63 }
40  
41   void
42   fdlist_init(void)
43   {
44 <  memset(&fd_hash, 0, sizeof(fd_hash));
45 <
46 <  fdlimit_cb = register_callback("changing_fdlimit", changing_fdlimit);
47 <  eventAddIsh("recalc_fdlimit", recalc_fdlimit, NULL, 58);
48 <  recalc_fdlimit(NULL);
44 >  /*
45 >   * Allow MAXCLIENTS_MIN clients even at the cost of MAX_BUFFER and
46 >   * some not really LEAKED_FDS
47 >   */
48 >  hard_fdlimit = IRCD_MAX(hard_fdlimit, LEAKED_FDS + MAX_BUFFER + MAXCLIENTS_MIN);
49 >  fd_table = xcalloc(sizeof(*fd_table) * hard_fdlimit);
50   }
51  
52 < void
53 < recalc_fdlimit(void *unused)
52 > static void
53 > fdlist_update_highest_fd(int fd, bool opening)
54   {
55 <  int fdmax;
56 <  struct rlimit limit;
55 >  if (fd < highest_fd)
56 >    return;
57  
58 <  if (!getrlimit(RLIMIT_NOFILE, &limit))
82 <  {
83 <    limit.rlim_cur = limit.rlim_max;
84 <    setrlimit(RLIMIT_NOFILE, &limit);
85 <  }
86 <
87 <  fdmax = getdtablesize();
88 <
89 <  /* allow MAXCLIENTS_MIN clients even at the cost of MAX_BUFFER and
90 <   * some not really LEAKED_FDS */
91 <  fdmax = IRCD_MAX(fdmax, LEAKED_FDS + MAX_BUFFER + MAXCLIENTS_MIN);
92 <
93 <  /* under no condition shall this raise over 65536
94 <   * for example user ip heap is sized 2*hard_fdlimit */
95 <  fdmax = IRCD_MIN(fdmax, 65536);
96 <
97 <  if (fdmax != hard_fdlimit)
98 <    execute_callback(fdlimit_cb, fdmax);
99 < }
100 <
101 < static inline unsigned int
102 < hash_fd(int fd)
103 < {
104 <  return (((unsigned) fd) % FD_HASH_SIZE);
105 < }
106 <
107 < fde_t *
108 < lookup_fd(int fd)
109 < {
110 <  fde_t *F = fd_hash[hash_fd(fd)];
58 >  assert(fd < hard_fdlimit);
59  
60 <  while (F)
60 >  if (fd > highest_fd)
61    {
62 <    if (F->fd == fd)
63 <      return (F);
64 <    F = F->hnext;
65 <  }
62 >    /*
63 >     * assert() that we are not closing a FD bigger than our known highest FD.
64 >     */
65 >    assert(opening == true);
66 >    highest_fd = fd;
67 >    return;
68 >  }
69 >
70 >  /* If we are here, then fd == highest_fd */
71 >  /*
72 >   * assert() that we are closing the highest FD; we can't be re-opening it.
73 >   */
74 >  assert(opening == false);
75  
76 <  return (NULL);
76 >  while (highest_fd >= 0 && fd_table[highest_fd].flags.open == false)
77 >    --highest_fd;
78   }
79  
80   /* Called to open a given filedescriptor */
81 < void
82 < fd_open(fde_t *F, int fd, int is_socket, const char *desc)
81 > fde_t *
82 > fd_open(int fd, bool is_socket, const char *desc)
83   {
84 <  unsigned int hashv = hash_fd(fd);
84 >  fde_t *F = &fd_table[fd];
85 >
86    assert(fd >= 0);
87 +  assert(F->fd == 0);
88 +  assert(F->flags.open == false);
89  
90 +  /*
91 +   * Note: normally we'd have to clear the other flags, but currently F
92 +   * is always cleared before calling us.
93 +   */
94    F->fd = fd;
95    F->comm_index = -1;
96 <  if (desc)
132 <    strlcpy(F->desc, desc, sizeof(F->desc));
133 <  /* Note: normally we'd have to clear the other flags,
134 <   * but currently F is always cleared before calling us.. */
135 <  F->flags.open = 1;
96 >  F->flags.open = true;
97    F->flags.is_socket = is_socket;
137  F->hnext = fd_hash[hashv];
138  fd_hash[hashv] = F;
98  
99 <  number_fd++;
99 >  if (desc)
100 >    F->desc = xstrndup(desc, FD_DESC_SIZE);
101 >
102 >  fdlist_update_highest_fd(F->fd, true);
103 >  ++number_fd;
104 >
105 >  return F;
106   }
107  
108   /* Called to close a given filedescriptor */
109 < void
109 > fde_t *
110   fd_close(fde_t *F)
111   {
112 <  unsigned int hashv = hash_fd(F->fd);
112 >  assert(F->fd >= 0);
113 >  assert(F->flags.open == true);
114  
115 <  if (F == fd_next_in_loop)
150 <    fd_next_in_loop = F->hnext;
151 <
152 <  if (F->flags.is_socket)
115 >  if (F->flags.is_socket == true)
116      comm_setselect(F, COMM_SELECT_WRITE | COMM_SELECT_READ, NULL, NULL, 0);
117  
118 <  delete_resolver_queries(F);
119 <
157 < #ifdef HAVE_LIBCRYPTO
158 <  if (F->ssl)
159 <    SSL_free(F->ssl);
160 < #endif
161 <
162 <  if (fd_hash[hashv] == F)
163 <    fd_hash[hashv] = F->hnext;
164 <  else {
165 <    fde_t *prev;
166 <
167 <    /* let it core if not found */
168 <    for (prev = fd_hash[hashv]; prev->hnext != F; prev = prev->hnext)
169 <      ;
170 <    prev->hnext = F->hnext;
171 <  }
118 >  if (tls_isusing(&F->ssl))
119 >    tls_free(&F->ssl);
120  
121 +  xfree(F->desc);
122    /* Unlike squid, we're actually closing the FD here! -- adrian */
123    close(F->fd);
124 <  number_fd--;
124 >  F->flags.open = false;  /* Must set F->flags.open == false before fdlist_update_highest_fd() */
125  
126 <  memset(F, 0, sizeof(fde_t));
127 < }
126 >  fdlist_update_highest_fd(F->fd, false);
127 >  --number_fd;
128  
129 < /*
181 < * fd_dump() - dump the list of active filedescriptors
182 < */
183 < void
184 < fd_dump(struct Client *source_p)
185 < {
186 <  int i;
187 <  fde_t *F;
129 >  memset(F, 0, sizeof(*F));
130  
131 <  for (i = 0; i < FD_HASH_SIZE; i++)
190 <    for (F = fd_hash[i]; F != NULL; F = F->hnext)
191 <      sendto_one(source_p, ":%s %d %s :fd %-5d desc '%s'",
192 <                 me.name, RPL_STATSDEBUG, source_p->name,
193 <                 F->fd, F->desc);
131 >  return F;
132   }
133  
134   /*
# Line 202 | Line 140 | fd_dump(struct Client *source_p)
140   void
141   fd_note(fde_t *F, const char *format, ...)
142   {
143 <  va_list args;
206 <
207 <  if (format != NULL)
143 >  if (format)
144    {
145 +    char buf[FD_DESC_SIZE + 1];
146 +    va_list args;
147 +
148      va_start(args, format);
149 <    vsnprintf(F->desc, sizeof(F->desc), format, args);
149 >    vsnprintf(buf, sizeof(buf), format, args);
150      va_end(args);
151 +
152 +    xfree(F->desc);
153 +    F->desc = xstrdup(buf);
154    }
155    else
156 <    F->desc[0] = '\0';
156 >  {
157 >    xfree(F->desc);
158 >    F->desc = NULL;
159 >  }
160   }
161  
162   /* Make sure stdio descriptors (0-2) and profiler descriptor (3)
# Line 220 | Line 165 | fd_note(fde_t *F, const char *format, ..
165   void
166   close_standard_fds(void)
167   {
168 <  int i;
224 <
225 <  for (i = 0; i < LOWEST_SAFE_FD; i++)
168 >  for (int i = 0; i < LOWEST_SAFE_FD; ++i)
169    {
170      close(i);
171 +
172      if (open("/dev/null", O_RDWR) < 0)
173 <      exit(-1); /* we're hosed if we can't even open /dev/null */
173 >      exit(EXIT_FAILURE); /* we're hosed if we can't even open /dev/null */
174    }
175   }
176  
177   void
178 < close_fds(fde_t *one)
178 > close_fds(void)
179   {
180 <  int i;
181 <  fde_t *F;
238 <
239 <  for (i = 0; i < FD_HASH_SIZE; i++)
240 <    for (F = fd_hash[i]; F != NULL; F = F->hnext)
241 <      if (F != one)
242 <        close(F->fd);
180 >  for (int fd = 0; fd <= highest_fd; ++fd)
181 >    close(fd);
182   }

Comparing ircd-hybrid/trunk/src/fdlist.c (property svn:keywords):
Revision 1618 by michael, Tue Oct 30 21:04:38 2012 UTC vs.
Revision 9101 by michael, Wed Jan 1 09:58:45 2020 UTC

# Line 1 | Line 1
1 < Id Revision
1 > Id

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)