io_wait.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /*
  2. * Copyright (C) 2005 iptelorg GmbH
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. /*!
  17. * \file
  18. * \brief Kamailio core :: tcp io wait common stuff used by tcp_main.c & tcp_read.c
  19. * (see io_wait.h)
  20. * \ingroup core
  21. * Module: \ref core
  22. */
  23. #ifndef NO_IO_WAIT
  24. #ifdef HAVE_EPOLL
  25. #include <unistd.h> /* close() */
  26. #endif
  27. #ifdef HAVE_DEVPOLL
  28. #include <sys/types.h> /* open */
  29. #include <sys/stat.h>
  30. #include <fcntl.h>
  31. #include <unistd.h> /* close, ioctl */
  32. #endif
  33. #include <stdlib.h> /* strtol() */
  34. #include "io_wait.h"
  35. #include "ut.h" /* get_sys_ver() */
  36. #include "mem/mem.h"
  37. #ifndef local_malloc
  38. #define local_malloc pkg_malloc
  39. #endif
  40. #ifndef local_free
  41. #define local_free pkg_free
  42. #endif
  43. char* poll_support="poll"
  44. #ifdef HAVE_EPOLL
  45. ", epoll_lt, epoll_et"
  46. #endif
  47. #ifdef HAVE_SIGIO_RT
  48. ", sigio_rt"
  49. #endif
  50. #ifdef HAVE_SELECT
  51. ", select"
  52. #endif
  53. #ifdef HAVE_KQUEUE
  54. ", kqueue"
  55. #endif
  56. #ifdef HAVE_DEVPOLL
  57. ", /dev/poll"
  58. #endif
  59. ;
  60. char* poll_method_str[POLL_END]={ "none", "poll", "epoll_lt", "epoll_et",
  61. "sigio_rt", "select", "kqueue", "/dev/poll"
  62. };
  63. int _os_ver=0; /* os version number */
  64. #ifdef HAVE_SIGIO_RT
  65. static int _sigio_init=0;
  66. static int _sigio_crt_rtsig;
  67. static sigset_t _sigio_rtsig_used;
  68. #endif
  69. #ifdef HAVE_SIGIO_RT
  70. /* sigio specific init
  71. * returns -1 on error, 0 on success */
  72. static int init_sigio(io_wait_h* h, int rsig)
  73. {
  74. int r;
  75. int n;
  76. int signo;
  77. int start_sig;
  78. sigset_t oldset;
  79. if (!_sigio_init){
  80. _sigio_init=1;
  81. _sigio_crt_rtsig=SIGRTMIN;
  82. sigemptyset(&_sigio_rtsig_used);
  83. }
  84. h->signo=0;
  85. if (rsig==0){
  86. start_sig=_sigio_crt_rtsig;
  87. n=SIGRTMAX-SIGRTMIN;
  88. }else{
  89. if ((rsig < SIGRTMIN) || (rsig >SIGRTMAX)){
  90. LM_CRIT("real time signal %d out of range [%d, %d]\n",
  91. rsig, SIGRTMIN, SIGRTMAX);
  92. goto error;
  93. }
  94. start_sig=rsig;
  95. n=0;
  96. }
  97. sigemptyset(&h->sset);
  98. sigemptyset(&oldset);
  99. retry1:
  100. /* get current block mask */
  101. if (sigprocmask(SIG_BLOCK, &h->sset, &oldset )==-1){
  102. if (errno==EINTR) goto retry1;
  103. LM_ERR("1st sigprocmask failed: %s [%d]\n", strerror(errno), errno);
  104. /* try to continue */
  105. }
  106. for (r=start_sig; r<=(n+start_sig); r++){
  107. signo=(r>SIGRTMAX)?r-SIGRTMAX+SIGRTMIN:r;
  108. if (! sigismember(&_sigio_rtsig_used, signo) &&
  109. ! sigismember(&oldset, signo)){
  110. sigaddset(&_sigio_rtsig_used, signo);
  111. h->signo=signo;
  112. _sigio_crt_rtsig=(signo<SIGRTMAX)?signo+1:SIGRTMIN;
  113. break;
  114. }
  115. }
  116. if (h->signo==0){
  117. LM_CRIT("%s\n", rsig?"could not assign requested real-time signal":
  118. "out of real-time signals");
  119. goto error;
  120. }
  121. LM_DBG("trying signal %d... \n", h->signo);
  122. if (sigaddset(&h->sset, h->signo)==-1){
  123. LM_ERR("sigaddset failed for %d: %s [%d]\n",
  124. h->signo, strerror(errno), errno);
  125. goto error;
  126. }
  127. if (sigaddset(&h->sset, SIGIO)==-1){
  128. LM_ERR("sigaddset failed for %d: %s [%d]\n",
  129. SIGIO, strerror(errno), errno);
  130. goto error;
  131. }
  132. retry:
  133. if (sigprocmask(SIG_BLOCK, &h->sset, 0)==-1){
  134. if (errno==EINTR) goto retry;
  135. LM_ERR("sigprocmask failed: %s [%d]\n",
  136. strerror(errno), errno);
  137. goto error;
  138. }
  139. return 0;
  140. error:
  141. h->signo=0;
  142. sigemptyset(&h->sset);
  143. return -1;
  144. }
  145. /* sigio specific destroy */
  146. static void destroy_sigio(io_wait_h* h)
  147. {
  148. if (h->signo){
  149. sigprocmask(SIG_UNBLOCK, &h->sset, 0);
  150. sigemptyset(&h->sset);
  151. sigdelset(&_sigio_rtsig_used, h->signo);
  152. h->signo=0;
  153. }
  154. }
  155. #endif
  156. #ifdef HAVE_EPOLL
  157. /* epoll specific init
  158. * returns -1 on error, 0 on success */
  159. static int init_epoll(io_wait_h* h)
  160. {
  161. again:
  162. h->epfd=epoll_create(h->max_fd_no);
  163. if (h->epfd==-1){
  164. if (errno==EINTR) goto again;
  165. LM_ERR("epoll_create: %s [%d]\n", strerror(errno), errno);
  166. return -1;
  167. }
  168. return 0;
  169. }
  170. static void destroy_epoll(io_wait_h* h)
  171. {
  172. if (h->epfd!=-1){
  173. close(h->epfd);
  174. h->epfd=-1;
  175. }
  176. }
  177. #endif
  178. #ifdef HAVE_KQUEUE
  179. /* kqueue specific init
  180. * returns -1 on error, 0 on success */
  181. static int init_kqueue(io_wait_h* h)
  182. {
  183. again:
  184. h->kq_fd=kqueue();
  185. if (h->kq_fd==-1){
  186. if (errno==EINTR) goto again;
  187. LM_ERR("kqueue: %s [%d]\n", strerror(errno), errno);
  188. return -1;
  189. }
  190. return 0;
  191. }
  192. static void destroy_kqueue(io_wait_h* h)
  193. {
  194. if (h->kq_fd!=-1){
  195. close(h->kq_fd);
  196. h->kq_fd=-1;
  197. }
  198. }
  199. #endif
  200. #ifdef HAVE_DEVPOLL
  201. /* /dev/poll specific init
  202. * returns -1 on error, 0 on success */
  203. static int init_devpoll(io_wait_h* h)
  204. {
  205. again:
  206. h->dpoll_fd=open("/dev/poll", O_RDWR);
  207. if (h->dpoll_fd==-1){
  208. if (errno==EINTR) goto again;
  209. LM_ERR("open: %s [%d]\n", strerror(errno), errno);
  210. return -1;
  211. }
  212. return 0;
  213. }
  214. static void destroy_devpoll(io_wait_h* h)
  215. {
  216. if (h->dpoll_fd!=-1){
  217. close(h->dpoll_fd);
  218. h->dpoll_fd=-1;
  219. }
  220. }
  221. #endif
  222. #ifdef HAVE_SELECT
  223. static int init_select(io_wait_h* h)
  224. {
  225. FD_ZERO(&h->master_rset);
  226. FD_ZERO(&h->master_wset);
  227. return 0;
  228. }
  229. #endif
  230. /*
  231. * returns 0 on success, and an error message on error
  232. */
  233. char* check_poll_method(enum poll_types poll_method)
  234. {
  235. char* ret;
  236. ret=0;
  237. if (_os_ver==0)
  238. _os_ver=get_sys_version(0,0,0);
  239. switch(poll_method){
  240. case POLL_NONE:
  241. break;
  242. case POLL_POLL:
  243. /* always supported */
  244. break;
  245. case POLL_SELECT:
  246. /* should be always supported */
  247. #ifndef HAVE_SELECT
  248. ret="select not supported, try re-compiling with -DHAVE_SELECT";
  249. #endif
  250. break;
  251. case POLL_EPOLL_LT:
  252. case POLL_EPOLL_ET:
  253. #ifndef HAVE_EPOLL
  254. ret="epoll not supported, try re-compiling with -DHAVE_EPOLL";
  255. #else
  256. /* only on 2.6 + */
  257. if (_os_ver<0x020542) /* if ver < 2.5.66 */
  258. ret="epoll not supported on kernels < 2.6";
  259. #endif
  260. break;
  261. case POLL_SIGIO_RT:
  262. #ifndef HAVE_SIGIO_RT
  263. ret="sigio_rt not supported, try re-compiling with"
  264. " -DHAVE_SIGIO_RT";
  265. #else
  266. /* only on 2.2 + ?? */
  267. if (_os_ver<0x020200) /* if ver < 2.2.0 */
  268. ret="epoll not supported on kernels < 2.2 (?)";
  269. #endif
  270. break;
  271. case POLL_KQUEUE:
  272. #ifndef HAVE_KQUEUE
  273. ret="kqueue not supported, try re-compiling with -DHAVE_KQUEUE";
  274. #else
  275. /* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD 2.9, Darwin, DragonFly */
  276. #ifdef __OS_freebsd
  277. /* all DragonFly versions have kqueque */
  278. #ifndef __OS_dragonfly
  279. if (_os_ver<0x0401) /* if ver < 4.1 */
  280. ret="kqueue not supported on FreeBSD < 4.1";
  281. #endif /* __OS_dragonfly */
  282. #elif defined (__OS_netbsd)
  283. if (_os_ver<0x020000) /* if ver < 2.0 */
  284. ret="kqueue not supported on NetBSD < 2.0";
  285. #elif defined (__OS_openbsd)
  286. if (_os_ver<0x0209) /* if ver < 2.9 ? */
  287. ret="kqueue not supported on OpenBSD < 2.9 (?)";
  288. #endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
  289. #endif
  290. break;
  291. case POLL_DEVPOLL:
  292. #ifndef HAVE_DEVPOLL
  293. ret="/dev/poll not supported, try re-compiling with"
  294. " -DHAVE_DEVPOLL";
  295. #else
  296. /* only in Solaris >= 7.0 (?) */
  297. #ifdef __OS_solaris
  298. if (_os_ver<0x0507) /* ver < 5.7 */
  299. ret="/dev/poll not supported on Solaris < 7.0 (SunOS 5.7)";
  300. #endif
  301. #endif
  302. break;
  303. default:
  304. ret="unknown not supported method";
  305. }
  306. return ret;
  307. }
  308. enum poll_types choose_poll_method()
  309. {
  310. enum poll_types poll_method;
  311. if (_os_ver==0)
  312. _os_ver=get_sys_version(0,0,0);
  313. poll_method=0;
  314. #ifdef HAVE_EPOLL
  315. if (_os_ver>=0x020542) /* if ver >= 2.5.66 */
  316. poll_method=POLL_EPOLL_LT; /* or POLL_EPOLL_ET */
  317. #endif
  318. #ifdef HAVE_KQUEUE
  319. if (poll_method==0)
  320. /* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD 2.9, Darwin, DragonFly */
  321. #ifdef __OS_freebsd
  322. /* all DragonFly versions have kqueque */
  323. #ifndef __OS_dragonfly
  324. if (_os_ver>=0x0401) /* if ver >= 4.1 */
  325. #endif /**__OS_dragonfly */
  326. #elif defined (__OS_netbsd)
  327. if (_os_ver>=0x020000) /* if ver >= 2.0 */
  328. #elif defined (__OS_openbsd)
  329. if (_os_ver>=0x0209) /* if ver >= 2.9 (?) */
  330. #endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
  331. poll_method=POLL_KQUEUE;
  332. #endif
  333. #ifdef HAVE_DEVPOLL
  334. #ifdef __OS_solaris
  335. if (poll_method==0)
  336. /* only in Solaris >= 7.0 (?) */
  337. if (_os_ver>=0x0507) /* if ver >=SunOS 5.7 */
  338. poll_method=POLL_DEVPOLL;
  339. #endif
  340. #endif
  341. #ifdef HAVE_SIGIO_RT
  342. if (poll_method==0)
  343. if (_os_ver>=0x020200) /* if ver >= 2.2.0 */
  344. poll_method=POLL_SIGIO_RT;
  345. #endif
  346. if (poll_method==0) poll_method=POLL_POLL;
  347. return poll_method;
  348. }
  349. char* poll_method_name(enum poll_types poll_method)
  350. {
  351. if ((poll_method>=POLL_NONE) && (poll_method<POLL_END))
  352. return poll_method_str[poll_method];
  353. else
  354. return "invalid poll method";
  355. }
  356. /* converts a string into a poll_method
  357. * returns POLL_NONE (0) on error, else the corresponding poll type */
  358. enum poll_types get_poll_type(char* s)
  359. {
  360. int r;
  361. int l;
  362. l=strlen(s);
  363. for (r=POLL_END-1; r>POLL_NONE; r--)
  364. if ((strlen(poll_method_str[r])==l) &&
  365. (strncasecmp(poll_method_str[r], s, l)==0))
  366. break;
  367. return r;
  368. }
  369. /* initializes the static vars/arrays
  370. * params: h - pointer to the io_wait_h that will be initialized
  371. * max_fd - maximum allowed fd number
  372. * poll_m - poll method (0 for automatic best fit)
  373. */
  374. int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
  375. {
  376. char * poll_err;
  377. if (_os_ver==0) _os_ver=get_sys_version(0,0,0);
  378. memset(h, 0, sizeof(*h));
  379. h->max_fd_no=max_fd;
  380. #ifdef HAVE_EPOLL
  381. h->epfd=-1;
  382. #endif
  383. #ifdef HAVE_KQUEUE
  384. h->kq_fd=-1;
  385. #endif
  386. #ifdef HAVE_DEVPOLL
  387. h->dpoll_fd=-1;
  388. #endif
  389. poll_err=check_poll_method(poll_method);
  390. /* set an appropiate poll method */
  391. if (poll_err || (poll_method==0)){
  392. poll_method=choose_poll_method();
  393. if (poll_err){
  394. LM_ERR("%s, using %s instead\n",
  395. poll_err, poll_method_str[poll_method]);
  396. }else{
  397. LM_INFO("using %s as the io watch method (auto detected)\n",
  398. poll_method_str[poll_method]);
  399. }
  400. }
  401. h->poll_method=poll_method;
  402. /* common stuff, everybody has fd_hash */
  403. h->fd_hash=local_malloc(sizeof(*(h->fd_hash))*h->max_fd_no);
  404. if (h->fd_hash==0){
  405. LM_CRIT("could not alloc fd hashtable (%ld bytes)\n",
  406. (long)sizeof(*(h->fd_hash))*h->max_fd_no );
  407. goto error;
  408. }
  409. memset((void*)h->fd_hash, 0, sizeof(*(h->fd_hash))*h->max_fd_no);
  410. switch(poll_method){
  411. case POLL_POLL:
  412. #ifdef HAVE_SELECT
  413. case POLL_SELECT:
  414. #endif
  415. #ifdef HAVE_SIGIO_RT
  416. case POLL_SIGIO_RT:
  417. #endif
  418. #ifdef HAVE_DEVPOLL
  419. case POLL_DEVPOLL:
  420. #endif
  421. h->fd_array=local_malloc(sizeof(*(h->fd_array))*h->max_fd_no);
  422. if (h->fd_array==0){
  423. LM_CRIT("could not alloc fd array (%ld bytes)\n",
  424. (long)sizeof(*(h->fd_hash))*h->max_fd_no);
  425. goto error;
  426. }
  427. memset((void*)h->fd_array, 0, sizeof(*(h->fd_array))*h->max_fd_no);
  428. #ifdef HAVE_SIGIO_RT
  429. if ((poll_method==POLL_SIGIO_RT) && (init_sigio(h, 0)<0)){
  430. LM_CRIT("sigio init failed\n");
  431. goto error;
  432. }
  433. #endif
  434. #ifdef HAVE_DEVPOLL
  435. if ((poll_method==POLL_DEVPOLL) && (init_devpoll(h)<0)){
  436. LM_CRIT("/dev/poll init failed\n");
  437. goto error;
  438. }
  439. #endif
  440. #ifdef HAVE_SELECT
  441. if ((poll_method==POLL_SELECT) && (init_select(h)<0)){
  442. LM_CRIT("select init failed\n");
  443. goto error;
  444. }
  445. #endif
  446. break;
  447. #ifdef HAVE_EPOLL
  448. case POLL_EPOLL_LT:
  449. case POLL_EPOLL_ET:
  450. h->ep_array=local_malloc(sizeof(*(h->ep_array))*h->max_fd_no);
  451. if (h->ep_array==0){
  452. LM_CRIT("could not alloc epoll array\n");
  453. goto error;
  454. }
  455. memset((void*)h->ep_array, 0, sizeof(*(h->ep_array))*h->max_fd_no);
  456. if (init_epoll(h)<0){
  457. LM_CRIT("epoll init failed\n");
  458. goto error;
  459. }
  460. break;
  461. #endif
  462. #ifdef HAVE_KQUEUE
  463. case POLL_KQUEUE:
  464. h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE;
  465. /* kevent returns different events for read & write
  466. => to get all the possible events in one call we
  467. need twice the number of added fds + space
  468. for possible changelist errors.
  469. OTOH if memory is to be saved at all costs, one can
  470. decrease the array size.
  471. */
  472. h->kq_array_size=2 * h->max_fd_no + h->kq_changes_size;
  473. h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->kq_array_size);
  474. if (h->kq_array==0){
  475. LM_CRIT("could not alloc kqueue event array\n");
  476. goto error;
  477. }
  478. h->kq_changes=local_malloc(sizeof(*(h->kq_changes))*
  479. h->kq_changes_size);
  480. if (h->kq_changes==0){
  481. LM_CRIT("could not alloc kqueue changes array\n");
  482. goto error;
  483. }
  484. h->kq_nchanges=0;
  485. memset((void*)h->kq_array, 0,
  486. sizeof(*(h->kq_array))*h->kq_array_size);
  487. memset((void*)h->kq_changes, 0,
  488. sizeof(*(h->kq_changes))* h->kq_changes_size);
  489. if (init_kqueue(h)<0){
  490. LM_CRIT("kqueue init failed\n");
  491. goto error;
  492. }
  493. break;
  494. #endif
  495. default:
  496. LM_CRIT("unknown/unsupported poll method %s (%d)\n",
  497. poll_method_str[poll_method], poll_method);
  498. goto error;
  499. }
  500. return 0;
  501. error:
  502. return -1;
  503. }
  504. /* destroys everything init_io_wait allocated */
  505. void destroy_io_wait(io_wait_h* h)
  506. {
  507. switch(h->poll_method){
  508. #ifdef HAVE_EPOLL
  509. case POLL_EPOLL_LT:
  510. case POLL_EPOLL_ET:
  511. destroy_epoll(h);
  512. if (h->ep_array){
  513. local_free(h->ep_array);
  514. h->ep_array=0;
  515. }
  516. break;
  517. #endif
  518. #ifdef HAVE_KQUEUE
  519. case POLL_KQUEUE:
  520. destroy_kqueue(h);
  521. if (h->kq_array){
  522. local_free(h->kq_array);
  523. h->kq_array=0;
  524. }
  525. if (h->kq_changes){
  526. local_free(h->kq_changes);
  527. h->kq_changes=0;
  528. }
  529. break;
  530. #endif
  531. #ifdef HAVE_SIGIO_RT
  532. case POLL_SIGIO_RT:
  533. destroy_sigio(h);
  534. break;
  535. #endif
  536. #ifdef HAVE_DEVPOLL
  537. case POLL_DEVPOLL:
  538. destroy_devpoll(h);
  539. break;
  540. #endif
  541. default: /*do nothing*/
  542. ;
  543. }
  544. if (h->fd_array){
  545. local_free(h->fd_array);
  546. h->fd_array=0;
  547. }
  548. if (h->fd_hash){
  549. local_free(h->fd_hash);
  550. h->fd_hash=0;
  551. }
  552. }
  553. #endif /*ifndef NO_IO_WAIT */