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