Coverage Report

Created: 2025-07-18 06:32

/src/opensips/io_wait.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2005 iptelorg GmbH
3
 *
4
 * This file is part of opensips, a free SIP server.
5
 *
6
 * opensips is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version
10
 *
11
 * opensips is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19
 *
20
 * History:
21
 * --------
22
 *  2005-06-15  created by andrei
23
 *  2005-06-26  added kqueue (andrei)
24
 *  2005-07-04  added /dev/poll (andrei)
25
 */
26
27
/*!
28
 * \file
29
 * \brief OpenSIPS TCP IO wait common functions
30
 */
31
32
33
#ifdef HAVE_EPOLL
34
#include <unistd.h> /* close() */
35
#endif
36
#ifdef HAVE_DEVPOLL
37
#include <sys/types.h> /* open */
38
#include <sys/stat.h>
39
#include <fcntl.h>
40
#include <unistd.h> /* close, ioctl */
41
#endif
42
43
#include <sys/utsname.h> /* uname() */
44
#include <stdlib.h> /* strtol() */
45
#include "io_wait.h"
46
47
48
#include "mem/mem.h"
49
50
#ifndef local_malloc
51
0
#define local_malloc pkg_malloc
52
#endif
53
#ifndef local_free
54
0
#define local_free pkg_free
55
#endif
56
57
char* poll_support="poll"
58
#ifdef HAVE_EPOLL
59
", epoll"
60
#endif
61
#ifdef HAVE_SIGIO_RT
62
", sigio_rt"
63
#endif
64
#ifdef HAVE_SELECT
65
", select"
66
#endif
67
#ifdef HAVE_KQUEUE
68
", kqueue"
69
#endif
70
#ifdef HAVE_DEVPOLL
71
", /dev/poll"
72
#endif
73
;
74
75
/*! supported poll methods */
76
char* poll_method_str[POLL_END]={ "none", "poll", "epoll",
77
                  "sigio_rt", "select", "kqueue",  "/dev/poll"
78
                };
79
80
#ifdef HAVE_SIGIO_RT
81
static int _sigio_init=0;
82
static int _sigio_crt_rtsig;
83
static sigset_t _sigio_rtsig_used;
84
#endif
85
86
87
88
#ifdef HAVE_SIGIO_RT
89
/*!
90
 * \brief sigio specific init
91
 * \param h IO handle
92
 * \param rsig real time signal
93
 * \return returns -1 on error, 0 on success
94
 */
95
static int init_sigio(io_wait_h* h, int rsig)
96
0
{
97
0
  int r;
98
0
  int n;
99
0
  int signo;
100
0
  int start_sig;
101
0
  sigset_t oldset;
102
103
0
  if (!_sigio_init){
104
0
    _sigio_init=1;
105
0
    _sigio_crt_rtsig=SIGRTMIN;
106
0
    sigemptyset(&_sigio_rtsig_used);
107
0
  }
108
0
  h->signo=0;
109
110
0
  if (rsig==0){
111
0
    start_sig=_sigio_crt_rtsig;
112
0
    n=SIGRTMAX-SIGRTMIN;
113
0
  }else{
114
0
    if ((rsig < SIGRTMIN) || (rsig >SIGRTMAX)){
115
0
      LM_CRIT("real time signal %d out of"
116
0
        " range  [%d, %d]\n", rsig, SIGRTMIN, SIGRTMAX);
117
0
      goto error;
118
0
    }
119
0
    start_sig=rsig;
120
0
    n=0;
121
0
  }
122
123
0
  sigemptyset(&h->sset);
124
0
  sigemptyset(&oldset);
125
0
retry1:
126
  /* get current block mask */
127
0
  if (sigprocmask(SIG_BLOCK, &h->sset, &oldset )==-1){
128
0
    if (errno==EINTR) goto retry1;
129
0
    LM_ERR("1st sigprocmask failed: %s [%d]\n",
130
0
        strerror(errno), errno);
131
    /* try to continue */
132
0
  }
133
134
0
  for (r=start_sig; r<=(n+start_sig); r++){
135
0
    signo=(r>SIGRTMAX)?r-SIGRTMAX+SIGRTMIN:r;
136
0
    if (! sigismember(&_sigio_rtsig_used, signo) &&
137
0
      ! sigismember(&oldset, signo)){
138
0
      sigaddset(&_sigio_rtsig_used, signo);
139
0
      h->signo=signo;
140
0
      _sigio_crt_rtsig=(signo<SIGRTMAX)?signo+1:SIGRTMIN;
141
0
      break;
142
0
    }
143
0
  }
144
145
0
  if (h->signo==0){
146
0
      LM_CRIT("init_sigio: %s\n",
147
0
          rsig?"could not assign requested real-time signal":
148
0
             "out of real-time signals");
149
0
      goto error;
150
0
  }
151
152
0
  LM_DBG("trying signal %d... \n", h->signo);
153
154
0
  if (sigaddset(&h->sset, h->signo)==-1){
155
0
    LM_ERR("sigaddset failed for %d: %s [%d]\n",
156
0
        h->signo, strerror(errno), errno);
157
0
    goto error;
158
0
  }
159
0
  if (sigaddset(&h->sset, SIGIO)==-1){
160
0
    LM_ERR("sigaddset failed for %d: %s [%d]\n",
161
0
        SIGIO, strerror(errno), errno);
162
0
    goto error;
163
0
  }
164
0
retry:
165
0
  if (sigprocmask(SIG_BLOCK, &h->sset, 0)==-1){
166
0
    if (errno==EINTR) goto retry;
167
0
    LM_ERR("sigprocmask failed: %s [%d]\n",
168
0
        strerror(errno), errno);
169
0
    goto error;
170
0
  }
171
0
  return 0;
172
0
error:
173
0
  h->signo=0;
174
0
  sigemptyset(&h->sset);
175
0
  return -1;
176
0
}
177
178
179
180
/*!
181
 * \brief sigio specific destroy
182
 * \param h IO handle
183
 */
184
static void destroy_sigio(io_wait_h* h)
185
0
{
186
0
  if (h->signo){
187
0
    sigprocmask(SIG_UNBLOCK, &h->sset, 0);
188
0
    sigemptyset(&h->sset);
189
0
    sigdelset(&_sigio_rtsig_used, h->signo);
190
0
    h->signo=0;
191
0
  }
192
0
}
193
#endif
194
195
196
197
#ifdef HAVE_EPOLL
198
/*!
199
 * \brief epoll specific init
200
 * \param h IO handle
201
 * \return -1 on error, 0 on success
202
 */
203
static int init_epoll(io_wait_h* h)
204
0
{
205
0
again:
206
0
  h->epfd=epoll_create(h->max_fd_no);
207
0
  if (h->epfd==-1){
208
0
    if (errno==EINTR) goto again;
209
0
    LM_ERR("epoll_create: %s [%d]\n",
210
0
        strerror(errno), errno);
211
0
    return -1;
212
0
  }
213
0
  return 0;
214
0
}
215
216
/*!
217
 * \brief epoll specific destroy
218
 * \param h IO handle
219
 */
220
static void destroy_epoll(io_wait_h* h)
221
0
{
222
0
  if (h->epfd!=-1){
223
0
    close(h->epfd);
224
0
    h->epfd=-1;
225
0
  }
226
0
}
227
#endif
228
229
230
231
#ifdef HAVE_KQUEUE
232
/*!
233
 * \brief kqueue specific init
234
 * \param h IO handle
235
 * \return -1 on error, 0 on success
236
 */
237
static int init_kqueue(io_wait_h* h)
238
{
239
again:
240
  h->kq_fd=kqueue();
241
  if (h->kq_fd==-1){
242
    if (errno==EINTR) goto again;
243
    LM_ERR("kqueue: %s [%d]\n",
244
        strerror(errno), errno);
245
    return -1;
246
  }
247
  return 0;
248
}
249
250
251
/*!
252
 * \brief kqueue specific destroy
253
 * \param h IO handle
254
 */
255
static void destroy_kqueue(io_wait_h* h)
256
{
257
  if (h->kq_fd!=-1){
258
    close(h->kq_fd);
259
    h->kq_fd=-1;
260
  }
261
}
262
#endif
263
264
265
266
#ifdef HAVE_DEVPOLL
267
/*!
268
 * \brief /dev/poll specific init
269
 * \param h IO handle
270
 * \return -1 on error, 0 on success */
271
static int init_devpoll(io_wait_h* h)
272
{
273
again:
274
  h->dpoll_fd=open("/dev/poll", O_RDWR);
275
  if (h->dpoll_fd==-1){
276
    if (errno==EINTR) goto again;
277
    LM_ERR("open: %s [%d]\n",
278
        strerror(errno), errno);
279
    return -1;
280
  }
281
  return 0;
282
}
283
284
285
/*!
286
 * \brief dev/poll specific destroy
287
 * \param h IO handle
288
 */
289
static void destroy_devpoll(io_wait_h* h)
290
{
291
  if (h->dpoll_fd!=-1){
292
    close(h->dpoll_fd);
293
    h->dpoll_fd=-1;
294
  }
295
}
296
#endif
297
298
299
300
#ifdef HAVE_SELECT
301
/*!
302
 * \brief select specific init
303
 * \param h IO handle
304
 * \return zero
305
 * \todo make this method void, and remove the check in io_wait.c
306
 */
307
static int init_select(io_wait_h* h)
308
0
{
309
0
  FD_ZERO(&h->master_set);
310
0
  return 0;
311
0
}
312
#endif
313
314
315
316
/*!
317
 * \brief return system version
318
 * Return system version (major.minor.minor2) as (major<<16)|(minor)<<8|(minor2)
319
 * (if some of them are missing, they are set to 0)
320
 * if the parameters are not null they are set to the coresp. part
321
 * \param major major version
322
 * \param minor minor version
323
 * \param minor2 minor2 version
324
 * \return (major<<16)|(minor)<<8|(minor2)
325
 */
326
static unsigned int get_sys_version(int* major, int* minor, int* minor2)
327
0
{
328
0
  struct utsname un;
329
0
  int m1;
330
0
  int m2;
331
0
  int m3;
332
0
  char* p;
333
334
0
  memset (&un, 0, sizeof(un));
335
0
  m1=m2=m3=0;
336
  /* get sys version */
337
0
  uname(&un);
338
0
  m1=strtol(un.release, &p, 10);
339
0
  if (*p=='.'){
340
0
    p++;
341
0
    m2=strtol(p, &p, 10);
342
0
    if (*p=='.'){
343
0
      p++;
344
0
      m3=strtol(p, &p, 10);
345
0
    }
346
0
  }
347
0
  if (major) *major=m1;
348
0
  if (minor) *minor=m2;
349
0
  if (minor2) *minor2=m3;
350
0
  return ((m1<<16)|(m2<<8)|(m3));
351
0
}
352
353
354
355
/*!
356
 * \brief Check preferred OS poll method
357
 * \param poll_method supported IO poll methods
358
 * \return 0 on success, and an error message on error
359
 */
360
char* check_poll_method(enum poll_types poll_method)
361
0
{
362
0
  char* ret;
363
0
  unsigned int os_ver;
364
365
0
  ret=0;
366
0
  os_ver=get_sys_version(0,0,0);
367
0
  (void)os_ver;
368
0
  switch(poll_method){
369
0
    case POLL_NONE:
370
0
      break;
371
0
    case POLL_POLL:
372
      /* always supported */
373
0
      break;
374
0
    case POLL_SELECT:
375
      /* should be always supported */
376
#ifndef HAVE_SELECT
377
      ret="select not supported, try re-compiling with -DHAVE_SELECT";
378
#endif
379
0
      break;
380
0
    case POLL_EPOLL:
381
#ifndef HAVE_EPOLL
382
      ret="epoll not supported, try re-compiling with -DHAVE_EPOLL";
383
#else
384
      /* only on 2.6 + */
385
0
      if (os_ver<0x020542) /* if ver < 2.5.66 */
386
0
        ret="epoll not supported on kernels < 2.6";
387
0
#endif
388
0
      break;
389
0
    case POLL_SIGIO_RT:
390
#ifndef HAVE_SIGIO_RT
391
      ret="sigio_rt not supported, try re-compiling with"
392
        " -DHAVE_SIGIO_RT";
393
#else
394
      /* only on 2.2 +  ?? */
395
0
      if (os_ver<0x020200) /* if ver < 2.2.0 */
396
0
        ret="epoll not supported on kernels < 2.2 (?)";
397
0
#endif
398
0
      break;
399
0
    case POLL_KQUEUE:
400
0
#ifndef HAVE_KQUEUE
401
0
      ret="kqueue not supported, try re-compiling with -DHAVE_KQUEUE";
402
#else
403
    /* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD 2.9, Darwin */
404
  #ifdef __OS_freebsd
405
      if (os_ver<0x0401) /* if ver < 4.1 */
406
        ret="kqueue not supported on FreeBSD < 4.1";
407
  #elif defined (__OS_netbsd)
408
      if (os_ver<0x020000) /* if ver < 2.0 */
409
        ret="kqueue not supported on NetBSD < 2.0";
410
  #elif defined (__OS_openbsd)
411
      if (os_ver<0x0209) /* if ver < 2.9 ? */
412
        ret="kqueue not supported on OpenBSD < 2.9 (?)";
413
  #endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
414
#endif
415
0
      break;
416
0
    case POLL_DEVPOLL:
417
0
#ifndef HAVE_DEVPOLL
418
0
      ret="/dev/poll not supported, try re-compiling with"
419
0
          " -DHAVE_DEVPOLL";
420
#else
421
  /* only in Solaris >= 7.0 (?) */
422
  #ifdef __OS_solaris
423
    if (os_ver<0x0507) /* ver < 5.7 */
424
      ret="/dev/poll not supported on Solaris < 7.0 (SunOS 5.7)";
425
  #endif
426
#endif
427
0
      break;
428
429
0
    default:
430
0
      ret="unknown not supported method";
431
0
  }
432
0
  return ret;
433
0
}
434
435
436
/*!
437
 * \brief Choose a IO poll method
438
 * \return the choosen poll method
439
 */
440
enum poll_types choose_poll_method(void)
441
0
{
442
0
  enum poll_types poll_method;
443
0
  unsigned int os_ver;
444
445
0
  os_ver=get_sys_version(0,0,0);
446
0
  (void)os_ver;
447
0
  poll_method=0;
448
0
#ifdef HAVE_EPOLL
449
0
  if (os_ver>=0x020542) /* if ver >= 2.5.66 */
450
0
    poll_method=POLL_EPOLL;
451
452
0
#endif
453
#ifdef HAVE_KQUEUE
454
  if (poll_method==0)
455
    /* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD 2.9, Darwin */
456
  #ifdef __OS_freebsd
457
    if (os_ver>=0x0401) /* if ver >= 4.1 */
458
  #elif defined (__OS_netbsd)
459
    if (os_ver>=0x020000) /* if ver >= 2.0 */
460
  #elif defined (__OS_openbsd)
461
    if (os_ver>=0x0209) /* if ver >= 2.9 (?) */
462
  #endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
463
      poll_method=POLL_KQUEUE;
464
#endif
465
#ifdef HAVE_DEVPOLL
466
  #ifdef __OS_solaris
467
  if (poll_method==0)
468
    /* only in Solaris >= 7.0 (?) */
469
    if (os_ver>=0x0507) /* if ver >=SunOS 5.7 */
470
      poll_method=POLL_DEVPOLL;
471
  #endif
472
#endif
473
0
#ifdef  HAVE_SIGIO_RT
474
0
    if (poll_method==0)
475
0
      if (os_ver>=0x020200) /* if ver >= 2.2.0 */
476
0
        poll_method=POLL_SIGIO_RT;
477
0
#endif
478
0
    if (poll_method==0) poll_method=POLL_POLL;
479
0
  return poll_method;
480
0
}
481
482
483
/*!
484
 * \brief output the IO poll method name
485
 * \param poll_method used poll method
486
 */
487
char* poll_method_name(enum poll_types poll_method)
488
0
{
489
0
  if ( poll_method<POLL_END )
490
0
    return poll_method_str[poll_method];
491
0
  else
492
0
    return "invalid poll method";
493
0
}
494
495
496
497
498
/*!
499
 * \brief converts a string into a poll_method
500
 * \param s converted string
501
 * \return POLL_NONE (0) on error, else the corresponding poll type
502
 */
503
enum poll_types get_poll_type(char* s)
504
0
{
505
0
  int r;
506
0
  unsigned int l;
507
508
0
  l=strlen(s);
509
0
  for (r=POLL_END-1; r>POLL_NONE; r--)
510
0
    if ((strlen(poll_method_str[r])==l) &&
511
0
      (strncasecmp(poll_method_str[r], s, l)==0))
512
0
      break;
513
0
  return r;
514
0
}
515
516
517
518
/*!
519
 * \brief initializes the static vars/arrays
520
 * \param  h - pointer to the io_wait_h that will be initialized
521
 * \param  max_fd - maximum allowed fd number
522
 * \param  poll_method - poll method (0 for automatic best fit)
523
 */
524
int init_io_wait(io_wait_h* h, char *name, int max_fd,
525
                enum poll_types poll_method, int max_prio)
526
0
{
527
0
  char * poll_err;
528
529
0
  memset(h, 0, sizeof(*h));
530
0
  h->name = name;
531
0
  h->max_prio = max_prio;
532
0
  h->max_fd_no=max_fd;
533
0
#ifdef HAVE_EPOLL
534
0
  h->epfd=-1;
535
0
#endif
536
#ifdef HAVE_KQUEUE
537
  h->kq_fd=-1;
538
#endif
539
#ifdef HAVE_DEVPOLL
540
  h->dpoll_fd=-1;
541
#endif
542
0
  poll_err=check_poll_method(poll_method);
543
544
  /* set an appropiate poll method */
545
0
  if (poll_err || (poll_method==0)){
546
0
    poll_method=choose_poll_method();
547
0
    if (poll_err){
548
0
      LM_ERR("%s, using %s instead\n",
549
0
          poll_err, poll_method_str[poll_method]);
550
0
    }else{
551
0
      LM_INFO("using %s as the io watch method"
552
0
          " (auto detected)\n", poll_method_str[poll_method]);
553
0
    }
554
0
  }
555
556
0
  h->poll_method=poll_method;
557
558
  /* common stuff, everybody has fd_hash */
559
0
  h->fd_hash=local_malloc(sizeof(*(h->fd_hash))*h->max_fd_no);
560
0
  if (h->fd_hash==0){
561
0
    LM_CRIT("could not alloc fd hashtable (%ld bytes)\n",
562
0
          (long)sizeof(*(h->fd_hash))*h->max_fd_no );
563
0
    goto error;
564
0
  }
565
0
  memset((void*)h->fd_hash, 0, sizeof(*(h->fd_hash))*h->max_fd_no);
566
567
  /* init the fd array as needed for priority ordering */
568
0
  h->fd_array=local_malloc(sizeof(*(h->fd_array))*h->max_fd_no);
569
0
  if (h->fd_array==0){
570
0
    LM_CRIT("could not alloc fd array (%ld bytes)\n",
571
0
          (long)sizeof(*(h->fd_hash))*h->max_fd_no);
572
0
    goto error;
573
0
  }
574
0
  memset((void*)h->fd_array, 0, sizeof(*(h->fd_array))*h->max_fd_no);
575
  /* array with indexes in fd_array where the priority changes */
576
0
  h->prio_idx=local_malloc(sizeof(*(h->prio_idx))*h->max_prio);
577
0
  if (h->prio_idx==0){
578
0
    LM_CRIT("could not alloc fd array (%ld bytes)\n",
579
0
          (long)sizeof(*(h->prio_idx))*h->max_prio);
580
0
    goto error;
581
0
  }
582
0
  memset((void*)h->prio_idx, 0, sizeof(*(h->prio_idx))*h->max_prio);
583
584
0
  switch(poll_method){
585
0
    case POLL_POLL:
586
0
      break;
587
0
#ifdef HAVE_SELECT
588
0
    case POLL_SELECT:
589
0
      if ((poll_method==POLL_SELECT) && (init_select(h)<0)){
590
0
        LM_CRIT("select init failed\n");
591
0
        goto error;
592
0
      }
593
0
      break;
594
0
#endif
595
#ifdef HAVE_DEVPOLL
596
    case POLL_DEVPOLL:
597
      if ((poll_method==POLL_DEVPOLL) && (init_devpoll(h)<0)){
598
        LM_CRIT("/dev/poll init failed\n");
599
        goto error;
600
      }
601
      h->dp_changes=local_malloc(sizeof(*(h->dp_changes))*h->max_fd_no);
602
      if (h->dp_changes==0){
603
        LM_CRIT("could not alloc db changes array (%ld bytes)\n",
604
              (long)sizeof(*(h->dp_changes))*h->max_fd_no);
605
        goto error;
606
      }
607
      memset((void*)h->dp_changes, 0,
608
        sizeof(*(h->dp_changes))*h->max_fd_no);
609
      break;
610
#endif
611
0
#ifdef HAVE_SIGIO_RT
612
0
    case POLL_SIGIO_RT:
613
0
      if ((poll_method==POLL_SIGIO_RT) && (init_sigio(h, 0)<0)){
614
0
        LM_CRIT("sigio init failed\n");
615
0
        goto error;
616
0
      }
617
0
      break;
618
0
#endif
619
0
#ifdef HAVE_EPOLL
620
0
    case POLL_EPOLL:
621
0
      h->ep_array=local_malloc(sizeof(*(h->ep_array))*h->max_fd_no);
622
0
      if (h->ep_array==0){
623
0
        LM_CRIT("could not alloc epoll array\n");
624
0
        goto error;
625
0
      }
626
0
      memset((void*)h->ep_array, 0, sizeof(*(h->ep_array))*h->max_fd_no);
627
0
      if (init_epoll(h)<0){
628
0
        LM_CRIT("epoll init failed\n");
629
0
        goto error;
630
0
      }
631
0
      break;
632
0
#endif
633
#ifdef HAVE_KQUEUE
634
    case POLL_KQUEUE:
635
      h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->max_fd_no);
636
      if (h->kq_array==0){
637
        LM_CRIT("could not alloc kqueue event array\n");
638
        goto error;
639
      }
640
      h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE;
641
      h->kq_changes=local_malloc(sizeof(*(h->kq_changes))*
642
                    h->kq_changes_size);
643
      if (h->kq_changes==0){
644
        LM_CRIT("could not alloc kqueue changes array\n");
645
        goto error;
646
      }
647
      h->kq_nchanges=0;
648
      memset((void*)h->kq_array, 0, sizeof(*(h->kq_array))*h->max_fd_no);
649
      memset((void*)h->kq_changes, 0,
650
            sizeof(*(h->kq_changes))* h->kq_changes_size);
651
      if (init_kqueue(h)<0){
652
        LM_CRIT("kqueue init failed\n");
653
        goto error;
654
      }
655
      break;
656
#endif
657
0
    default:
658
0
      LM_CRIT("unknown/unsupported poll method %s (%d)\n",
659
0
            poll_method_str[poll_method], poll_method);
660
0
      goto error;
661
0
  }
662
0
  return 0;
663
0
error:
664
0
  return -1;
665
0
}
666
667
668
669
/*!
670
 * \brief destroys everything init_io_wait allocated
671
 * \param h IO handle
672
 */
673
void destroy_io_wait(io_wait_h* h)
674
0
{
675
0
  switch(h->poll_method){
676
0
#ifdef HAVE_EPOLL
677
0
    case POLL_EPOLL:
678
0
      destroy_epoll(h);
679
0
      if (h->ep_array){
680
0
        local_free(h->ep_array);
681
0
        h->ep_array=0;
682
0
      }
683
0
    break;
684
0
#endif
685
#ifdef HAVE_KQUEUE
686
    case POLL_KQUEUE:
687
      destroy_kqueue(h);
688
      if (h->kq_array){
689
        local_free(h->kq_array);
690
        h->kq_array=0;
691
      }
692
      if (h->kq_changes){
693
        local_free(h->kq_changes);
694
        h->kq_changes=0;
695
      }
696
      break;
697
#endif
698
0
#ifdef HAVE_SIGIO_RT
699
0
    case POLL_SIGIO_RT:
700
0
      destroy_sigio(h);
701
0
      break;
702
0
#endif
703
#ifdef HAVE_DEVPOLL
704
    case POLL_DEVPOLL:
705
      destroy_devpoll(h);
706
      if (h->dp_changes){
707
        local_free(h->dp_changes);
708
        h->dp_changes=0;
709
      }
710
      break;
711
#endif
712
0
    default: /*do  nothing*/
713
0
      ;
714
0
  }
715
0
    if (h->fd_array){
716
0
      local_free(h->fd_array);
717
0
      h->fd_array=0;
718
0
    }
719
0
    if (h->fd_hash){
720
0
      local_free(h->fd_hash);
721
0
      h->fd_hash=0;
722
0
    }
723
0
    if (h->prio_idx){
724
0
      local_free(h->prio_idx);
725
0
      h->prio_idx=0;
726
0
    }
727
728
0
}
729
730
731
void fix_poll_method( enum poll_types *poll_method )
732
0
{
733
0
  char* poll_err;
734
735
  /* fix config variables */
736
  /* they can have only positive values due the config parser so we can
737
   * ignore most of them */
738
0
  poll_err=check_poll_method(*poll_method);
739
740
  /* set an appropiate poll method */
741
0
  if (poll_err || (*poll_method==0)){
742
0
    *poll_method=choose_poll_method();
743
0
    if (poll_err){
744
0
      LM_ERR("%s, using %s instead\n",
745
0
          poll_err, poll_method_name(*poll_method));
746
0
    }else{
747
0
      LM_INFO("using %s as the IO watch method"
748
0
          " (auto detected)\n", poll_method_name(*poll_method));
749
0
    }
750
0
  }else{
751
0
      LM_INFO("using %s as the IO watch method (config)\n",
752
0
          poll_method_name(*poll_method));
753
0
  }
754
755
0
  return;
756
0
}
757
758
759
int io_set_app_flag( io_wait_h *h , int type, int app_flag)
760
0
{
761
0
  int i;
762
0
  int res=0;
763
764
0
  for( i=0 ; i<h->fd_no ; i++) {
765
0
      if (h->fd_hash[i].fd<=0 && h->fd_hash[i].type==type) {
766
0
        h->fd_hash[i].app_flags |= app_flag;
767
0
        res = 1;
768
0
      }
769
0
  }
770
0
  return res;
771
0
}
772
773
774
int io_check_app_flag( io_wait_h *h , int app_flag)
775
0
{
776
0
  int i;
777
778
0
  for( i=0 ; i<h->fd_no ; i++) {
779
0
      if ( h->fd_hash[i].fd<=0 &&
780
0
      (h->fd_hash[i].app_flags & app_flag) )
781
0
        return 1;
782
0
  }
783
  /* nothing found, return false*/
784
0
  return 0;
785
786
0
}
787