DBusLoop: move OOM flag in watches inside the DBusWatch
[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-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 *watches;
60   DBusList *timeouts;
61   int callback_list_serial;
62   int watch_count;
63   int timeout_count;
64   int depth; /**< number of recursive runs */
65   DBusList *need_dispatch;
66 };
67
68 static short
69 watch_flags_to_poll_events (unsigned int flags)
70 {
71   short events = 0;
72
73   if (flags & DBUS_WATCH_READABLE)
74     events |= _DBUS_POLLIN;
75   if (flags & DBUS_WATCH_WRITABLE)
76     events |= _DBUS_POLLOUT;
77
78   return events;
79 }
80
81 static unsigned int
82 watch_flags_from_poll_revents (short revents)
83 {
84   unsigned int condition = 0;
85
86   if (revents & _DBUS_POLLIN)
87     condition |= DBUS_WATCH_READABLE;
88   if (revents & _DBUS_POLLOUT)
89     condition |= DBUS_WATCH_WRITABLE;
90   if (revents & _DBUS_POLLHUP)
91     condition |= DBUS_WATCH_HANGUP;
92   if (revents & _DBUS_POLLERR)
93     condition |= DBUS_WATCH_ERROR;
94
95   return condition;
96 }
97
98 typedef enum
99 {
100   CALLBACK_WATCH,
101   CALLBACK_TIMEOUT
102 } CallbackType;
103
104 typedef struct
105 {
106   int refcount;
107   CallbackType type;
108 } Callback;
109
110 typedef struct
111 {
112   Callback callback;
113   DBusWatch *watch;
114 } WatchCallback;
115
116 typedef struct
117 {
118   Callback callback;
119   DBusTimeout *timeout;
120   unsigned long last_tv_sec;
121   unsigned long last_tv_usec;
122 } TimeoutCallback;
123
124 #define WATCH_CALLBACK(callback)   ((WatchCallback*)callback)
125 #define TIMEOUT_CALLBACK(callback) ((TimeoutCallback*)callback)
126
127 static WatchCallback*
128 watch_callback_new (DBusWatch         *watch)
129 {
130   WatchCallback *cb;
131
132   cb = dbus_new (WatchCallback, 1);
133   if (cb == NULL)
134     return NULL;
135
136   cb->watch = watch;
137   cb->callback.refcount = 1;
138   cb->callback.type = CALLBACK_WATCH;
139   
140   return cb;
141 }
142
143 static TimeoutCallback*
144 timeout_callback_new (DBusTimeout         *timeout)
145 {
146   TimeoutCallback *cb;
147
148   cb = dbus_new (TimeoutCallback, 1);
149   if (cb == NULL)
150     return NULL;
151
152   cb->timeout = timeout;
153   _dbus_get_current_time (&cb->last_tv_sec,
154                           &cb->last_tv_usec);
155   cb->callback.refcount = 1;    
156   cb->callback.type = CALLBACK_TIMEOUT;
157   
158   return cb;
159 }
160
161 static Callback * 
162 callback_ref (Callback *cb)
163 {
164   _dbus_assert (cb->refcount > 0);
165   
166   cb->refcount += 1;
167
168   return cb;
169 }
170
171 static void
172 callback_unref (Callback *cb)
173 {
174   _dbus_assert (cb->refcount > 0);
175
176   cb->refcount -= 1;
177
178   if (cb->refcount == 0)
179     {
180       dbus_free (cb);
181     }
182 }
183
184 static dbus_bool_t
185 add_callback (DBusLoop  *loop,
186               DBusList **list,
187               Callback *cb)
188 {
189
190   if (!_dbus_list_append (list, cb))
191     return FALSE;
192
193   loop->callback_list_serial += 1;
194
195   switch (cb->type)
196     {
197     case CALLBACK_WATCH:
198       loop->watch_count += 1;
199       break;
200     case CALLBACK_TIMEOUT:
201       loop->timeout_count += 1;
202       break;
203     }
204   
205   return TRUE;
206 }
207
208 static void
209 remove_callback (DBusLoop  *loop,
210                  DBusList **list,
211                  DBusList *link)
212 {
213   Callback *cb = link->data;
214   
215   switch (cb->type)
216     {
217     case CALLBACK_WATCH:
218       loop->watch_count -= 1;
219       break;
220     case CALLBACK_TIMEOUT:
221       loop->timeout_count -= 1;
222       break;
223     }
224   
225   callback_unref (cb);
226   _dbus_list_remove_link (list, link);
227   loop->callback_list_serial += 1;
228 }
229
230 DBusLoop*
231 _dbus_loop_new (void)
232 {
233   DBusLoop *loop;
234
235   loop = dbus_new0 (DBusLoop, 1);
236   if (loop == NULL)
237     return NULL;
238
239   loop->refcount = 1;
240   
241   return loop;
242 }
243
244 DBusLoop *
245 _dbus_loop_ref (DBusLoop *loop)
246 {
247   _dbus_assert (loop != NULL);
248   _dbus_assert (loop->refcount > 0);
249
250   loop->refcount += 1;
251
252   return loop;
253 }
254
255 void
256 _dbus_loop_unref (DBusLoop *loop)
257 {
258   _dbus_assert (loop != NULL);
259   _dbus_assert (loop->refcount > 0);
260
261   loop->refcount -= 1;
262   if (loop->refcount == 0)
263     {
264       while (loop->need_dispatch)
265         {
266           DBusConnection *connection = _dbus_list_pop_first (&loop->need_dispatch);
267
268           dbus_connection_unref (connection);
269         }
270       
271       dbus_free (loop);
272     }
273 }
274
275 dbus_bool_t
276 _dbus_loop_add_watch (DBusLoop  *loop,
277                       DBusWatch *watch)
278 {
279   WatchCallback *wcb;
280
281   wcb = watch_callback_new (watch);
282   if (wcb == NULL)
283     return FALSE;
284
285   if (!add_callback (loop, &loop->watches, (Callback*) wcb))
286     {
287       callback_unref ((Callback*) wcb);
288       return FALSE;
289     }
290   
291   return TRUE;
292 }
293
294 void
295 _dbus_loop_remove_watch (DBusLoop         *loop,
296                          DBusWatch        *watch)
297 {
298   DBusList *link;
299
300   /* fd.o #33336: we want people to remove their watches before invalidating
301    * them */
302   _dbus_assert (dbus_watch_get_socket (watch) != -1);
303
304   link = _dbus_list_get_first_link (&loop->watches);
305   while (link != NULL)
306     {
307       DBusList *next = _dbus_list_get_next_link (&loop->watches, link);
308       WatchCallback *this = link->data;
309
310       _dbus_assert (this->callback.type == CALLBACK_WATCH);
311
312       if (this->watch == watch)
313         {
314           remove_callback (loop, &loop->watches, link);
315
316           return;
317         }
318       
319       link = next;
320     }
321
322   _dbus_warn ("could not find watch %p to remove\n", watch);
323 }
324
325 dbus_bool_t
326 _dbus_loop_add_timeout (DBusLoop           *loop,
327                         DBusTimeout        *timeout)
328 {
329   TimeoutCallback *tcb;
330
331   tcb = timeout_callback_new (timeout);
332   if (tcb == NULL)
333     return FALSE;
334
335   if (!add_callback (loop, &loop->timeouts, (Callback*) tcb))
336     {
337       callback_unref ((Callback*) tcb);
338       return FALSE;
339     }
340   
341   return TRUE;
342 }
343
344 void
345 _dbus_loop_remove_timeout (DBusLoop           *loop,
346                            DBusTimeout        *timeout)
347 {
348   DBusList *link;
349   
350   link = _dbus_list_get_first_link (&loop->timeouts);
351   while (link != NULL)
352     {
353       DBusList *next = _dbus_list_get_next_link (&loop->timeouts, link);
354       TimeoutCallback *this = link->data;
355
356       _dbus_assert (this->callback.type == CALLBACK_TIMEOUT);
357
358       if (this->timeout == timeout)
359         {
360           remove_callback (loop, &loop->timeouts, link);
361           
362           return;
363         }
364       
365       link = next;
366     }
367
368   _dbus_warn ("could not find timeout %p to remove\n", timeout);
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
464 dbus_bool_t
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
502 dbus_bool_t
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
519 dbus_bool_t
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->watches == NULL && loop->timeouts == 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->watches);
580   while (link != NULL)
581     {
582       DBusList *next = _dbus_list_get_next_link (&loop->watches, link);
583       Callback *cb = link->data;
584       unsigned int flags;
585       WatchCallback *wcb;
586       int fd;
587
588       _dbus_assert (cb->type == CALLBACK_WATCH);
589
590       wcb = WATCH_CALLBACK (cb);
591       fd = dbus_watch_get_socket (wcb->watch);
592
593       if (_dbus_watch_get_oom_last_time (wcb->watch))
594         {
595           /* we skip this one this time, but reenable it next time,
596            * and have a timeout on this iteration
597            */
598           _dbus_watch_set_oom_last_time (wcb->watch, FALSE);
599           oom_watch_pending = TRUE;
600
601           retval = TRUE; /* return TRUE here to keep the loop going,
602                           * since we don't know the watch is inactive
603                           */
604
605 #if MAINLOOP_SPEW
606           _dbus_verbose ("  skipping watch on fd %d as it was out of memory last time\n",
607                          fd);
608 #endif
609         }
610       else if (_DBUS_UNLIKELY (fd == -1))
611         {
612           _dbus_warn ("watch %p was invalidated but not removed; "
613               "removing it now\n", wcb->watch);
614           _dbus_loop_remove_watch (loop, wcb->watch);
615         }
616       else if (dbus_watch_get_enabled (wcb->watch))
617         {
618           watches_for_fds[n_fds] = wcb;
619
620           callback_ref (cb);
621
622           flags = dbus_watch_get_flags (wcb->watch);
623
624           fds[n_fds].fd = fd;
625           fds[n_fds].revents = 0;
626           fds[n_fds].events = watch_flags_to_poll_events (flags);
627
628 #if MAINLOOP_SPEW
629           _dbus_verbose ("  polling watch on fd %d  %s\n",
630                          loop->fds[loop->n_fds].fd, watch_flags_to_string (flags));
631 #endif
632
633           n_fds += 1;
634         }
635       else
636         {
637 #if MAINLOOP_SPEW
638           _dbus_verbose ("  skipping disabled watch on fd %d  %s\n",
639                          fd,
640                          watch_flags_to_string (dbus_watch_get_flags (wcb->watch)));
641 #endif
642         }
643
644       link = next;
645     }
646   
647   timeout = -1;
648   if (loop->timeout_count > 0)
649     {
650       unsigned long tv_sec;
651       unsigned long tv_usec;
652       
653       _dbus_get_current_time (&tv_sec, &tv_usec);
654
655       link = _dbus_list_get_first_link (&loop->timeouts);
656       while (link != NULL)
657         {
658           DBusList *next = _dbus_list_get_next_link (&loop->timeouts, link);
659           Callback *cb = link->data;
660
661           _dbus_assert (cb->type == CALLBACK_TIMEOUT);
662
663           if (dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)->timeout))
664             {
665               TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb);
666               int msecs_remaining;
667
668               check_timeout (tv_sec, tv_usec, tcb, &msecs_remaining);
669
670               if (timeout < 0)
671                 timeout = msecs_remaining;
672               else
673                 timeout = MIN (msecs_remaining, timeout);
674
675 #if MAINLOOP_SPEW
676               _dbus_verbose ("  timeout added, %d remaining, aggregate timeout %ld\n",
677                              msecs_remaining, timeout);
678 #endif
679               
680               _dbus_assert (timeout >= 0);
681                   
682               if (timeout == 0)
683                 break; /* it's not going to get shorter... */
684             }
685 #if MAINLOOP_SPEW
686           else
687             {
688               _dbus_verbose ("  skipping disabled timeout\n");
689             }
690 #endif
691           
692           link = next;
693         }
694     }
695
696   /* Never block if we have stuff to dispatch */
697   if (!block || loop->need_dispatch != NULL)
698     {
699       timeout = 0;
700 #if MAINLOOP_SPEW
701       _dbus_verbose ("  timeout is 0 as we aren't blocking\n");
702 #endif
703     }
704
705   /* if a watch is OOM, don't wait longer than the OOM
706    * wait to re-enable it
707    */
708   if (oom_watch_pending)
709     timeout = MIN (timeout, _dbus_get_oom_wait ());
710
711 #if MAINLOOP_SPEW
712   _dbus_verbose ("  polling on %d descriptors timeout %ld\n", n_fds, timeout);
713 #endif
714   
715   n_ready = _dbus_poll (fds, n_fds, timeout);
716
717   initial_serial = loop->callback_list_serial;
718
719   if (loop->timeout_count > 0)
720     {
721       unsigned long tv_sec;
722       unsigned long tv_usec;
723
724       _dbus_get_current_time (&tv_sec, &tv_usec);
725
726       /* It'd be nice to avoid this O(n) thingy here */
727       link = _dbus_list_get_first_link (&loop->timeouts);
728       while (link != NULL)
729         {
730           DBusList *next = _dbus_list_get_next_link (&loop->timeouts, link);
731           Callback *cb = link->data;
732
733           if (initial_serial != loop->callback_list_serial)
734             goto next_iteration;
735
736           if (loop->depth != orig_depth)
737             goto next_iteration;
738
739           _dbus_assert (cb->type == CALLBACK_TIMEOUT);
740
741           if (dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)->timeout))
742             {
743               TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb);
744               int msecs_remaining;
745               
746               if (check_timeout (tv_sec, tv_usec,
747                                  tcb, &msecs_remaining))
748                 {
749                   /* Save last callback time and fire this timeout */
750                   tcb->last_tv_sec = tv_sec;
751                   tcb->last_tv_usec = tv_usec;
752
753 #if MAINLOOP_SPEW
754                   _dbus_verbose ("  invoking timeout\n");
755 #endif
756
757                   /* can theoretically return FALSE on OOM, but we just
758                    * let it fire again later - in practice that's what
759                    * every wrapper callback in dbus-daemon used to do */
760                   dbus_timeout_handle (tcb->timeout);
761
762                   retval = TRUE;
763                 }
764               else
765                 {
766 #if MAINLOOP_SPEW
767                   _dbus_verbose ("  timeout has not expired\n");
768 #endif
769                 }
770             }
771 #if MAINLOOP_SPEW
772           else
773             {
774               _dbus_verbose ("  skipping invocation of disabled timeout\n");
775             }
776 #endif
777
778           link = next;
779         }
780     }
781       
782   if (n_ready > 0)
783     {
784       i = 0;
785       while (i < n_fds)
786         {
787           /* FIXME I think this "restart if we change the watches"
788            * approach could result in starving watches
789            * toward the end of the list.
790            */
791           if (initial_serial != loop->callback_list_serial)
792             goto next_iteration;
793
794           if (loop->depth != orig_depth)
795             goto next_iteration;
796
797           if (fds[i].revents != 0)
798             {
799               WatchCallback *wcb;
800               unsigned int condition;
801                   
802               wcb = watches_for_fds[i];
803               condition = watch_flags_from_poll_revents (fds[i].revents);
804
805               /* condition may still be 0 if we got some
806                * weird POLLFOO thing like POLLWRBAND
807                */
808                   
809               if (condition != 0 &&
810                   dbus_watch_get_enabled (wcb->watch))
811                 {
812                   dbus_bool_t oom;
813
814                   oom = !dbus_watch_handle (wcb->watch, condition);
815
816                   if (oom)
817                     {
818                       _dbus_watch_set_oom_last_time (wcb->watch, TRUE);
819                     }
820
821 #if MAINLOOP_SPEW
822                   _dbus_verbose ("  Invoked watch, oom = %d\n", oom);
823 #endif
824                   
825                   retval = TRUE;
826                 }
827
828               if (_DBUS_UNLIKELY (fds[i].revents & _DBUS_POLLNVAL))
829                 {
830                   DBusWatch *watch = _dbus_watch_ref (wcb->watch);
831
832                   _dbus_warn ("invalid request, socket fd %d not open\n",
833                       fds[i].fd);
834                   _dbus_loop_remove_watch (loop, watch);
835                   _dbus_watch_invalidate (watch);
836                   _dbus_watch_unref (watch);
837                 }
838             }
839               
840           ++i;
841         }
842     }
843       
844  next_iteration:
845 #if MAINLOOP_SPEW
846   _dbus_verbose ("  moving to next iteration\n");
847 #endif
848   
849   if (fds && fds != stack_fds)
850     dbus_free (fds);
851   if (watches_for_fds)
852     {
853       i = 0;
854       while (i < n_fds)
855         {
856           callback_unref (&watches_for_fds[i]->callback);
857           ++i;
858         }
859       
860       if (watches_for_fds != stack_watches_for_fds)
861         dbus_free (watches_for_fds);
862     }
863   
864   if (_dbus_loop_dispatch (loop))
865     retval = TRUE;
866   
867 #if MAINLOOP_SPEW
868   _dbus_verbose ("Returning %d\n", retval);
869 #endif
870   
871   return retval;
872 }
873
874 void
875 _dbus_loop_run (DBusLoop *loop)
876 {
877   int our_exit_depth;
878
879   _dbus_assert (loop->depth >= 0);
880   
881   _dbus_loop_ref (loop);
882   
883   our_exit_depth = loop->depth;
884   loop->depth += 1;
885
886   _dbus_verbose ("Running main loop, depth %d -> %d\n",
887                  loop->depth - 1, loop->depth);
888   
889   while (loop->depth != our_exit_depth)
890     _dbus_loop_iterate (loop, TRUE);
891
892   _dbus_loop_unref (loop);
893 }
894
895 void
896 _dbus_loop_quit (DBusLoop *loop)
897 {
898   _dbus_assert (loop->depth > 0);  
899   
900   loop->depth -= 1;
901
902   _dbus_verbose ("Quit main loop, depth %d -> %d\n",
903                  loop->depth + 1, loop->depth);
904 }
905
906 int
907 _dbus_get_oom_wait (void)
908 {
909 #ifdef DBUS_BUILD_TESTS
910   /* make tests go fast */
911   return 0;
912 #else
913   return 500;
914 #endif
915 }
916
917 void
918 _dbus_wait_for_memory (void)
919 {
920   _dbus_verbose ("Waiting for more memory\n");
921   _dbus_sleep_milliseconds (_dbus_get_oom_wait ());
922 }
923
924 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */