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