1 /* -*- mode: C; c-file-style: "gnu" -*- */ 2 /* dbus-mainloop.c Main loop utility 3 * 4 * Copyright (C) 2003, 2004 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 2.1 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23 24 #include "dbus-mainloop.h" 25 26 #ifndef DOXYGEN_SHOULD_SKIP_THIS 27 28 #include <dbus/dbus-list.h> 29 #include <dbus/dbus-sysdeps.h> 30 31 #define MAINLOOP_SPEW 0 32 33 #if MAINLOOP_SPEW 34 #ifdef DBUS_ENABLE_VERBOSE_MODE 35 static const char* 36 watch_flags_to_string (int flags) 37 { 38 const char *watch_type; 39 40 if ((flags & DBUS_WATCH_READABLE) && 41 (flags & DBUS_WATCH_WRITABLE)) 42 watch_type = "readwrite"; 43 else if (flags & DBUS_WATCH_READABLE) 44 watch_type = "read"; 45 else if (flags & DBUS_WATCH_WRITABLE) 46 watch_type = "write"; 47 else 48 watch_type = "not read or write"; 49 return watch_type; 50 } 51 #endif /* DBUS_ENABLE_VERBOSE_MODE */ 52 #endif /* MAINLOOP_SPEW */ 53 54 struct DBusLoop 55 { 56 int refcount; 57 DBusList *callbacks; 58 int callback_list_serial; 59 int watch_count; 60 int timeout_count; 61 int depth; /**< number of recursive runs */ 62 DBusList *need_dispatch; 63 }; 64 65 typedef enum 66 { 67 CALLBACK_WATCH, 68 CALLBACK_TIMEOUT 69 } CallbackType; 70 71 typedef struct 72 { 73 int refcount; 74 CallbackType type; 75 void *data; 76 DBusFreeFunction free_data_func; 77 } Callback; 78 79 typedef struct 80 { 81 Callback callback; 82 DBusWatchFunction function; 83 DBusWatch *watch; 84 /* last watch handle failed due to OOM */ 85 unsigned int last_iteration_oom : 1; 86 } WatchCallback; 87 88 typedef struct 89 { 90 Callback callback; 91 DBusTimeout *timeout; 92 DBusTimeoutFunction function; 93 unsigned long last_tv_sec; 94 unsigned long last_tv_usec; 95 } TimeoutCallback; 96 97 #define WATCH_CALLBACK(callback) ((WatchCallback*)callback) 98 #define TIMEOUT_CALLBACK(callback) ((TimeoutCallback*)callback) 99 100 static WatchCallback* 101 watch_callback_new (DBusWatch *watch, 102 DBusWatchFunction function, 103 void *data, 104 DBusFreeFunction free_data_func) 105 { 106 WatchCallback *cb; 107 108 cb = dbus_new (WatchCallback, 1); 109 if (cb == NULL) 110 return NULL; 111 112 cb->watch = watch; 113 cb->function = function; 114 cb->last_iteration_oom = FALSE; 115 cb->callback.refcount = 1; 116 cb->callback.type = CALLBACK_WATCH; 117 cb->callback.data = data; 118 cb->callback.free_data_func = free_data_func; 119 120 return cb; 121 } 122 123 static TimeoutCallback* 124 timeout_callback_new (DBusTimeout *timeout, 125 DBusTimeoutFunction function, 126 void *data, 127 DBusFreeFunction free_data_func) 128 { 129 TimeoutCallback *cb; 130 131 cb = dbus_new (TimeoutCallback, 1); 132 if (cb == NULL) 133 return NULL; 134 135 cb->timeout = timeout; 136 cb->function = function; 137 _dbus_get_current_time (&cb->last_tv_sec, 138 &cb->last_tv_usec); 139 cb->callback.refcount = 1; 140 cb->callback.type = CALLBACK_TIMEOUT; 141 cb->callback.data = data; 142 cb->callback.free_data_func = free_data_func; 143 144 return cb; 145 } 146 147 static Callback * 148 callback_ref (Callback *cb) 149 { 150 _dbus_assert (cb->refcount > 0); 151 152 cb->refcount += 1; 153 154 return cb; 155 } 156 157 static void 158 callback_unref (Callback *cb) 159 { 160 _dbus_assert (cb->refcount > 0); 161 162 cb->refcount -= 1; 163 164 if (cb->refcount == 0) 165 { 166 if (cb->free_data_func) 167 (* cb->free_data_func) (cb->data); 168 169 dbus_free (cb); 170 } 171 } 172 173 static dbus_bool_t 174 add_callback (DBusLoop *loop, 175 Callback *cb) 176 { 177 if (!_dbus_list_append (&loop->callbacks, cb)) 178 return FALSE; 179 180 loop->callback_list_serial += 1; 181 182 switch (cb->type) 183 { 184 case CALLBACK_WATCH: 185 loop->watch_count += 1; 186 break; 187 case CALLBACK_TIMEOUT: 188 loop->timeout_count += 1; 189 break; 190 } 191 192 return TRUE; 193 } 194 195 static void 196 remove_callback (DBusLoop *loop, 197 DBusList *link) 198 { 199 Callback *cb = link->data; 200 201 switch (cb->type) 202 { 203 case CALLBACK_WATCH: 204 loop->watch_count -= 1; 205 break; 206 case CALLBACK_TIMEOUT: 207 loop->timeout_count -= 1; 208 break; 209 } 210 211 callback_unref (cb); 212 _dbus_list_remove_link (&loop->callbacks, link); 213 loop->callback_list_serial += 1; 214 } 215 216 DBusLoop* 217 _dbus_loop_new (void) 218 { 219 DBusLoop *loop; 220 221 loop = dbus_new0 (DBusLoop, 1); 222 if (loop == NULL) 223 return NULL; 224 225 loop->refcount = 1; 226 227 return loop; 228 } 229 230 DBusLoop * 231 _dbus_loop_ref (DBusLoop *loop) 232 { 233 _dbus_assert (loop != NULL); 234 _dbus_assert (loop->refcount > 0); 235 236 loop->refcount += 1; 237 238 return loop; 239 } 240 241 void 242 _dbus_loop_unref (DBusLoop *loop) 243 { 244 _dbus_assert (loop != NULL); 245 _dbus_assert (loop->refcount > 0); 246 247 loop->refcount -= 1; 248 if (loop->refcount == 0) 249 { 250 while (loop->need_dispatch) 251 { 252 DBusConnection *connection = _dbus_list_pop_first (&loop->need_dispatch); 253 254 dbus_connection_unref (connection); 255 } 256 257 dbus_free (loop); 258 } 259 } 260 261 dbus_bool_t 262 _dbus_loop_add_watch (DBusLoop *loop, 263 DBusWatch *watch, 264 DBusWatchFunction function, 265 void *data, 266 DBusFreeFunction free_data_func) 267 { 268 WatchCallback *wcb; 269 270 wcb = watch_callback_new (watch, function, data, free_data_func); 271 if (wcb == NULL) 272 return FALSE; 273 274 if (!add_callback (loop, (Callback*) wcb)) 275 { 276 wcb->callback.free_data_func = NULL; /* don't want to have this side effect */ 277 callback_unref ((Callback*) wcb); 278 return FALSE; 279 } 280 281 return TRUE; 282 } 283 284 void 285 _dbus_loop_remove_watch (DBusLoop *loop, 286 DBusWatch *watch, 287 DBusWatchFunction function, 288 void *data) 289 { 290 DBusList *link; 291 292 link = _dbus_list_get_first_link (&loop->callbacks); 293 while (link != NULL) 294 { 295 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 296 Callback *this = link->data; 297 298 if (this->type == CALLBACK_WATCH && 299 WATCH_CALLBACK (this)->watch == watch && 300 this->data == data && 301 WATCH_CALLBACK (this)->function == function) 302 { 303 remove_callback (loop, link); 304 305 return; 306 } 307 308 link = next; 309 } 310 311 _dbus_warn ("could not find watch %p function %p data %p to remove\n", 312 watch, (void *)function, data); 313 } 314 315 dbus_bool_t 316 _dbus_loop_add_timeout (DBusLoop *loop, 317 DBusTimeout *timeout, 318 DBusTimeoutFunction function, 319 void *data, 320 DBusFreeFunction free_data_func) 321 { 322 TimeoutCallback *tcb; 323 324 tcb = timeout_callback_new (timeout, function, data, free_data_func); 325 if (tcb == NULL) 326 return FALSE; 327 328 if (!add_callback (loop, (Callback*) tcb)) 329 { 330 tcb->callback.free_data_func = NULL; /* don't want to have this side effect */ 331 callback_unref ((Callback*) tcb); 332 return FALSE; 333 } 334 335 return TRUE; 336 } 337 338 void 339 _dbus_loop_remove_timeout (DBusLoop *loop, 340 DBusTimeout *timeout, 341 DBusTimeoutFunction function, 342 void *data) 343 { 344 DBusList *link; 345 346 link = _dbus_list_get_first_link (&loop->callbacks); 347 while (link != NULL) 348 { 349 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 350 Callback *this = link->data; 351 352 if (this->type == CALLBACK_TIMEOUT && 353 TIMEOUT_CALLBACK (this)->timeout == timeout && 354 this->data == data && 355 TIMEOUT_CALLBACK (this)->function == function) 356 { 357 remove_callback (loop, link); 358 359 return; 360 } 361 362 link = next; 363 } 364 365 _dbus_warn ("could not find timeout %p function %p data %p to remove\n", 366 timeout, (void *)function, data); 367 } 368 369 /* Convolutions from GLib, there really must be a better way 370 * to do this. 371 */ 372 static dbus_bool_t 373 check_timeout (unsigned long tv_sec, 374 unsigned long tv_usec, 375 TimeoutCallback *tcb, 376 int *timeout) 377 { 378 long sec_remaining; 379 long msec_remaining; 380 unsigned long expiration_tv_sec; 381 unsigned long expiration_tv_usec; 382 long interval_seconds; 383 long interval_milliseconds; 384 int interval; 385 386 /* I'm pretty sure this function could suck (a lot) less */ 387 388 interval = dbus_timeout_get_interval (tcb->timeout); 389 390 interval_seconds = interval / 1000L; 391 interval_milliseconds = interval % 1000L; 392 393 expiration_tv_sec = tcb->last_tv_sec + interval_seconds; 394 expiration_tv_usec = tcb->last_tv_usec + interval_milliseconds * 1000; 395 if (expiration_tv_usec >= 1000000) 396 { 397 expiration_tv_usec -= 1000000; 398 expiration_tv_sec += 1; 399 } 400 401 sec_remaining = expiration_tv_sec - tv_sec; 402 /* need to force this to be signed, as it is intended to sometimes 403 * produce a negative result 404 */ 405 msec_remaining = ((long) expiration_tv_usec - (long) tv_usec) / 1000L; 406 407 #if MAINLOOP_SPEW 408 _dbus_verbose ("Interval is %ld seconds %ld msecs\n", 409 interval_seconds, 410 interval_milliseconds); 411 _dbus_verbose ("Now is %lu seconds %lu usecs\n", 412 tv_sec, tv_usec); 413 _dbus_verbose ("Last is %lu seconds %lu usecs\n", 414 tcb->last_tv_sec, tcb->last_tv_usec); 415 _dbus_verbose ("Exp is %lu seconds %lu usecs\n", 416 expiration_tv_sec, expiration_tv_usec); 417 _dbus_verbose ("Pre-correction, sec_remaining %ld msec_remaining %ld\n", 418 sec_remaining, msec_remaining); 419 #endif 420 421 /* We do the following in a rather convoluted fashion to deal with 422 * the fact that we don't have an integral type big enough to hold 423 * the difference of two timevals in milliseconds. 424 */ 425 if (sec_remaining < 0 || (sec_remaining == 0 && msec_remaining < 0)) 426 { 427 *timeout = 0; 428 } 429 else 430 { 431 if (msec_remaining < 0) 432 { 433 msec_remaining += 1000; 434 sec_remaining -= 1; 435 } 436 437 if (sec_remaining > (_DBUS_INT_MAX / 1000) || 438 msec_remaining > _DBUS_INT_MAX) 439 *timeout = _DBUS_INT_MAX; 440 else 441 *timeout = sec_remaining * 1000 + msec_remaining; 442 } 443 444 if (*timeout > interval) 445 { 446 /* This indicates that the system clock probably moved backward */ 447 _dbus_verbose ("System clock set backward! Resetting timeout.\n"); 448 449 tcb->last_tv_sec = tv_sec; 450 tcb->last_tv_usec = tv_usec; 451 452 *timeout = interval; 453 } 454 455 #if MAINLOOP_SPEW 456 _dbus_verbose (" timeout expires in %d milliseconds\n", *timeout); 457 #endif 458 459 return *timeout == 0; 460 } 461 462 dbus_bool_t 463 _dbus_loop_dispatch (DBusLoop *loop) 464 { 465 466 #if MAINLOOP_SPEW 467 _dbus_verbose (" %d connections to dispatch\n", _dbus_list_get_length (&loop->need_dispatch)); 468 #endif 469 470 if (loop->need_dispatch == NULL) 471 return FALSE; 472 473 next: 474 while (loop->need_dispatch != NULL) 475 { 476 DBusConnection *connection = _dbus_list_pop_first (&loop->need_dispatch); 477 478 while (TRUE) 479 { 480 DBusDispatchStatus status; 481 482 status = dbus_connection_dispatch (connection); 483 484 if (status == DBUS_DISPATCH_COMPLETE) 485 { 486 dbus_connection_unref (connection); 487 goto next; 488 } 489 else 490 { 491 if (status == DBUS_DISPATCH_NEED_MEMORY) 492 _dbus_wait_for_memory (); 493 } 494 } 495 } 496 497 return TRUE; 498 } 499 500 dbus_bool_t 501 _dbus_loop_queue_dispatch (DBusLoop *loop, 502 DBusConnection *connection) 503 { 504 if (_dbus_list_append (&loop->need_dispatch, connection)) 505 { 506 dbus_connection_ref (connection); 507 return TRUE; 508 } 509 else 510 return FALSE; 511 } 512 513 /* Returns TRUE if we invoked any timeouts or have ready file 514 * descriptors, which is just used in test code as a debug hack 515 */ 516 517 dbus_bool_t 518 _dbus_loop_iterate (DBusLoop *loop, 519 dbus_bool_t block) 520 { 521 #define N_STACK_DESCRIPTORS 64 522 dbus_bool_t retval; 523 DBusPollFD *fds; 524 DBusPollFD stack_fds[N_STACK_DESCRIPTORS]; 525 int n_fds; 526 WatchCallback **watches_for_fds; 527 WatchCallback *stack_watches_for_fds[N_STACK_DESCRIPTORS]; 528 int i; 529 DBusList *link; 530 int n_ready; 531 int initial_serial; 532 long timeout; 533 dbus_bool_t oom_watch_pending; 534 int orig_depth; 535 536 retval = FALSE; 537 538 fds = NULL; 539 watches_for_fds = NULL; 540 n_fds = 0; 541 oom_watch_pending = FALSE; 542 orig_depth = loop->depth; 543 544 #if MAINLOOP_SPEW 545 _dbus_verbose ("Iteration block=%d depth=%d timeout_count=%d watch_count=%d\n", 546 block, loop->depth, loop->timeout_count, loop->watch_count); 547 #endif 548 549 if (loop->callbacks == NULL) 550 goto next_iteration; 551 552 if (loop->watch_count > N_STACK_DESCRIPTORS) 553 { 554 fds = dbus_new0 (DBusPollFD, loop->watch_count); 555 556 while (fds == NULL) 557 { 558 _dbus_wait_for_memory (); 559 fds = dbus_new0 (DBusPollFD, loop->watch_count); 560 } 561 562 watches_for_fds = dbus_new (WatchCallback*, loop->watch_count); 563 while (watches_for_fds == NULL) 564 { 565 _dbus_wait_for_memory (); 566 watches_for_fds = dbus_new (WatchCallback*, loop->watch_count); 567 } 568 } 569 else 570 { 571 fds = stack_fds; 572 watches_for_fds = stack_watches_for_fds; 573 } 574 575 /* fill our array of fds and watches */ 576 n_fds = 0; 577 link = _dbus_list_get_first_link (&loop->callbacks); 578 while (link != NULL) 579 { 580 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 581 Callback *cb = link->data; 582 if (cb->type == CALLBACK_WATCH) 583 { 584 unsigned int flags; 585 WatchCallback *wcb = WATCH_CALLBACK (cb); 586 587 if (wcb->last_iteration_oom) 588 { 589 /* we skip this one this time, but reenable it next time, 590 * and have a timeout on this iteration 591 */ 592 wcb->last_iteration_oom = FALSE; 593 oom_watch_pending = TRUE; 594 595 retval = TRUE; /* return TRUE here to keep the loop going, 596 * since we don't know the watch is inactive 597 */ 598 599 #if MAINLOOP_SPEW 600 _dbus_verbose (" skipping watch on fd %d as it was out of memory last time\n", 601 dbus_watch_get_fd (wcb->watch)); 602 #endif 603 } 604 else if (dbus_watch_get_enabled (wcb->watch)) 605 { 606 watches_for_fds[n_fds] = wcb; 607 608 callback_ref (cb); 609 610 flags = dbus_watch_get_flags (wcb->watch); 611 612 fds[n_fds].fd = dbus_watch_get_fd (wcb->watch); 613 fds[n_fds].revents = 0; 614 fds[n_fds].events = 0; 615 if (flags & DBUS_WATCH_READABLE) 616 fds[n_fds].events |= _DBUS_POLLIN; 617 if (flags & DBUS_WATCH_WRITABLE) 618 fds[n_fds].events |= _DBUS_POLLOUT; 619 620 #if MAINLOOP_SPEW 621 _dbus_verbose (" polling watch on fd %d %s\n", 622 fds[n_fds].fd, watch_flags_to_string (flags)); 623 #endif 624 625 n_fds += 1; 626 } 627 else 628 { 629 #if MAINLOOP_SPEW 630 _dbus_verbose (" skipping disabled watch on fd %d %s\n", 631 dbus_watch_get_fd (wcb->watch), 632 watch_flags_to_string (dbus_watch_get_flags (wcb->watch))); 633 #endif 634 } 635 } 636 637 link = next; 638 } 639 640 timeout = -1; 641 if (loop->timeout_count > 0) 642 { 643 unsigned long tv_sec; 644 unsigned long tv_usec; 645 646 _dbus_get_current_time (&tv_sec, &tv_usec); 647 648 link = _dbus_list_get_first_link (&loop->callbacks); 649 while (link != NULL) 650 { 651 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 652 Callback *cb = link->data; 653 654 if (cb->type == CALLBACK_TIMEOUT && 655 dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)->timeout)) 656 { 657 TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb); 658 int msecs_remaining; 659 660 check_timeout (tv_sec, tv_usec, tcb, &msecs_remaining); 661 662 if (timeout < 0) 663 timeout = msecs_remaining; 664 else 665 timeout = MIN (msecs_remaining, timeout); 666 667 #if MAINLOOP_SPEW 668 _dbus_verbose (" timeout added, %d remaining, aggregate timeout %ld\n", 669 msecs_remaining, timeout); 670 #endif 671 672 _dbus_assert (timeout >= 0); 673 674 if (timeout == 0) 675 break; /* it's not going to get shorter... */ 676 } 677 #if MAINLOOP_SPEW 678 else if (cb->type == CALLBACK_TIMEOUT) 679 { 680 _dbus_verbose (" skipping disabled timeout\n"); 681 } 682 #endif 683 684 link = next; 685 } 686 } 687 688 /* Never block if we have stuff to dispatch */ 689 if (!block || loop->need_dispatch != NULL) 690 { 691 timeout = 0; 692 #if MAINLOOP_SPEW 693 _dbus_verbose (" timeout is 0 as we aren't blocking\n"); 694 #endif 695 } 696 697 /* if a watch is OOM, don't wait longer than the OOM 698 * wait to re-enable it 699 */ 700 if (oom_watch_pending) 701 timeout = MIN (timeout, _dbus_get_oom_wait ()); 702 703 #if MAINLOOP_SPEW 704 _dbus_verbose (" polling on %d descriptors timeout %ld\n", n_fds, timeout); 705 #endif 706 707 n_ready = _dbus_poll (fds, n_fds, timeout); 708 709 initial_serial = loop->callback_list_serial; 710 711 if (loop->timeout_count > 0) 712 { 713 unsigned long tv_sec; 714 unsigned long tv_usec; 715 716 _dbus_get_current_time (&tv_sec, &tv_usec); 717 718 /* It'd be nice to avoid this O(n) thingy here */ 719 link = _dbus_list_get_first_link (&loop->callbacks); 720 while (link != NULL) 721 { 722 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 723 Callback *cb = link->data; 724 725 if (initial_serial != loop->callback_list_serial) 726 goto next_iteration; 727 728 if (loop->depth != orig_depth) 729 goto next_iteration; 730 731 if (cb->type == CALLBACK_TIMEOUT && 732 dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)->timeout)) 733 { 734 TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb); 735 int msecs_remaining; 736 737 if (check_timeout (tv_sec, tv_usec, 738 tcb, &msecs_remaining)) 739 { 740 /* Save last callback time and fire this timeout */ 741 tcb->last_tv_sec = tv_sec; 742 tcb->last_tv_usec = tv_usec; 743 744 #if MAINLOOP_SPEW 745 _dbus_verbose (" invoking timeout\n"); 746 #endif 747 748 (* tcb->function) (tcb->timeout, 749 cb->data); 750 751 retval = TRUE; 752 } 753 else 754 { 755 #if MAINLOOP_SPEW 756 _dbus_verbose (" timeout has not expired\n"); 757 #endif 758 } 759 } 760 #if MAINLOOP_SPEW 761 else if (cb->type == CALLBACK_TIMEOUT) 762 { 763 _dbus_verbose (" skipping invocation of disabled timeout\n"); 764 } 765 #endif 766 767 link = next; 768 } 769 } 770 771 if (n_ready > 0) 772 { 773 i = 0; 774 while (i < n_fds) 775 { 776 /* FIXME I think this "restart if we change the watches" 777 * approach could result in starving watches 778 * toward the end of the list. 779 */ 780 if (initial_serial != loop->callback_list_serial) 781 goto next_iteration; 782 783 if (loop->depth != orig_depth) 784 goto next_iteration; 785 786 if (fds[i].revents != 0) 787 { 788 WatchCallback *wcb; 789 unsigned int condition; 790 791 wcb = watches_for_fds[i]; 792 793 condition = 0; 794 if (fds[i].revents & _DBUS_POLLIN) 795 condition |= DBUS_WATCH_READABLE; 796 if (fds[i].revents & _DBUS_POLLOUT) 797 condition |= DBUS_WATCH_WRITABLE; 798 if (fds[i].revents & _DBUS_POLLHUP) 799 condition |= DBUS_WATCH_HANGUP; 800 if (fds[i].revents & _DBUS_POLLERR) 801 condition |= DBUS_WATCH_ERROR; 802 803 /* condition may still be 0 if we got some 804 * weird POLLFOO thing like POLLWRBAND 805 */ 806 807 if (condition != 0 && 808 dbus_watch_get_enabled (wcb->watch)) 809 { 810 if (!(* wcb->function) (wcb->watch, 811 condition, 812 ((Callback*)wcb)->data)) 813 wcb->last_iteration_oom = TRUE; 814 815 #if MAINLOOP_SPEW 816 _dbus_verbose (" Invoked watch, oom = %d\n", 817 wcb->last_iteration_oom); 818 #endif 819 820 retval = TRUE; 821 } 822 } 823 824 ++i; 825 } 826 } 827 828 next_iteration: 829 #if MAINLOOP_SPEW 830 _dbus_verbose (" moving to next iteration\n"); 831 #endif 832 833 if (fds && fds != stack_fds) 834 dbus_free (fds); 835 if (watches_for_fds) 836 { 837 i = 0; 838 while (i < n_fds) 839 { 840 callback_unref (&watches_for_fds[i]->callback); 841 ++i; 842 } 843 844 if (watches_for_fds != stack_watches_for_fds) 845 dbus_free (watches_for_fds); 846 } 847 848 if (_dbus_loop_dispatch (loop)) 849 retval = TRUE; 850 851 #if MAINLOOP_SPEW 852 _dbus_verbose ("Returning %d\n", retval); 853 #endif 854 855 return retval; 856 } 857 858 void 859 _dbus_loop_run (DBusLoop *loop) 860 { 861 int our_exit_depth; 862 863 _dbus_assert (loop->depth >= 0); 864 865 _dbus_loop_ref (loop); 866 867 our_exit_depth = loop->depth; 868 loop->depth += 1; 869 870 _dbus_verbose ("Running main loop, depth %d -> %d\n", 871 loop->depth - 1, loop->depth); 872 873 while (loop->depth != our_exit_depth) 874 _dbus_loop_iterate (loop, TRUE); 875 876 _dbus_loop_unref (loop); 877 } 878 879 void 880 _dbus_loop_quit (DBusLoop *loop) 881 { 882 _dbus_assert (loop->depth > 0); 883 884 loop->depth -= 1; 885 886 _dbus_verbose ("Quit main loop, depth %d -> %d\n", 887 loop->depth + 1, loop->depth); 888 } 889 890 int 891 _dbus_get_oom_wait (void) 892 { 893 #ifdef DBUS_BUILD_TESTS 894 /* make tests go fast */ 895 return 0; 896 #else 897 return 500; 898 #endif 899 } 900 901 void 902 _dbus_wait_for_memory (void) 903 { 904 _dbus_verbose ("Waiting for more memory\n"); 905 _dbus_sleep_milliseconds (_dbus_get_oom_wait ()); 906 } 907 908 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */ 909