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