Move from mulit-threaded to single-threaded dbus communication
[profile/ivi/persistence-client-library.git] / src / persistence_client_library_dbus_service.c
1 /******************************************************************************
2  * Project         Persistency
3  * (c) copyright   2012
4  * Company         XS Embedded GmbH
5  *****************************************************************************/
6 /******************************************************************************
7  * This Source Code Form is subject to the terms of the
8  * Mozilla Public License, v. 2.0. If a  copy of the MPL was not distributed
9  * with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 ******************************************************************************/
11  /**
12  * @file           persistence_client_library_dbus_service.c
13  * @ingroup        Persistence client library
14  * @author         Ingo Huerner
15  * @brief          Implementation of the persistence client library dbus service.
16  * @see
17  */
18
19
20 #include "persistence_client_library_dbus_service.h"
21 #include "persistence_client_library_lc_interface.h"
22 #include "persistence_client_library_pas_interface.h"
23 #include "../include_protected/persistence_client_library_data_organization.h"
24
25 #include <stdio.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30
31 pthread_cond_t  gDbusInitializedCond = PTHREAD_COND_INITIALIZER;
32 pthread_mutex_t gDbusInitializedMtx  = PTHREAD_MUTEX_INITIALIZER;
33 pthread_mutex_t gDbusPendingRegMtx   = PTHREAD_MUTEX_INITIALIZER;
34 int gEfds = 0;
35
36 typedef enum EDBusObjectType
37 {
38    OT_NONE = 0,
39    OT_WATCH,
40    OT_TIMEOUT
41 } tDBusObjectType;
42
43
44 typedef struct SObjectEntry
45 {
46    tDBusObjectType objtype; /** libdbus' object */
47    union
48    {
49       DBusWatch * watch;      /** watch "object" */
50       DBusTimeout * timeout;  /** timeout "object" */
51    };
52 } tObjectEntry;
53
54
55
56 /// polling structure
57 typedef struct SPollInfo
58 {
59    int nfds;
60    struct pollfd fds[10];
61    tObjectEntry objects[10];
62 } tPollInfo;
63
64
65 /// polling information
66 static tPollInfo gPollInfo;
67
68 int bContinue = 0;
69
70 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
71
72
73 /* function to unregister ojbect path message handler */
74 static void unregisterMessageHandler(DBusConnection *connection, void *user_data)
75 {
76    DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("unregisterObjectPath\n"));
77 }
78
79 /* catches messages not directed to any registered object path ("garbage collector") */
80 static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connection, DBusMessage * message, void * user_data)
81 {
82    DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED;
83
84    // org.genivi.persistence.admin  S I G N A L
85    if((0==strcmp("org.genivi.persistence.admin", dbus_message_get_interface(message))))
86    {
87       if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
88       {
89          if((0==strcmp("PersistenceModeChanged", dbus_message_get_member(message))))
90          {
91             // to do handle signal
92             result = signal_persModeChange(connection, message);
93          }
94          else
95          {
96             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback -> unknown signal:"), DLT_STRING(dbus_message_get_interface(message)) );
97          }
98       }
99    }
100    // org.genivi.persistence.admin  S I G N A L
101    else if((0==strcmp("org.genivi.persistence.adminconsumer", dbus_message_get_interface(message))))
102    {
103       if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
104       {
105          pclNotification_s notifyStruct;
106          int validMessage = 0;
107
108          if((0==strcmp("PersistenceResChange", dbus_message_get_member(message))))
109          {
110             notifyStruct.pclKeyNotify_Status = pclNotifyStatus_changed;
111             validMessage = 1;
112          }
113          else if((0==strcmp("PersistenceResDelete", dbus_message_get_member(message))))
114          {
115             notifyStruct.pclKeyNotify_Status = pclNotifyStatus_deleted;
116             validMessage = 1;
117          }
118          else if((0==strcmp("PersistenceRes", dbus_message_get_member(message))))
119          {
120             notifyStruct.pclKeyNotify_Status = pclNotifyStatus_created;
121             validMessage = 1;
122          }
123
124          if(validMessage == 1)
125          {
126             DBusError error;
127             DBusMessage *reply;
128             dbus_error_init (&error);
129             char* ldbid;
130             char* user_no;
131             char* seat_no;
132
133             if (!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &notifyStruct.resource_id,
134                                                          DBUS_TYPE_STRING, &ldbid,
135                                                          DBUS_TYPE_STRING, &user_no,
136                                                          DBUS_TYPE_STRING, &seat_no,
137                                                          DBUS_TYPE_INVALID))
138             {
139                reply = dbus_message_new_error(message, error.name, error.message);
140
141                if (reply == 0)
142                {
143                   DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback => DBus No memory"), DLT_STRING(dbus_message_get_interface(message)) );
144                }
145
146                if (!dbus_connection_send(connection, reply, 0))
147                {
148                   DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback => DBus No memory"), DLT_STRING(dbus_message_get_interface(message)) );
149                }
150
151                result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;;
152                dbus_message_unref(reply);
153             }
154             else
155             {
156                notifyStruct.ldbid       = atoi(ldbid);
157                notifyStruct.user_no     = atoi(user_no);
158                notifyStruct.seat_no     = atoi(seat_no);
159
160                // call the registered callback function
161                gChangeNotifyCallback(&notifyStruct);
162
163                result = DBUS_HANDLER_RESULT_HANDLED;
164             }
165             dbus_connection_flush(connection);
166          }
167       }
168    }
169    // org.genivi.persistence.admin  P R O P E R T Y
170    else  if((0==strcmp("org.freedesktop.DBus.Properties", dbus_message_get_interface(message))))
171    {
172       if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
173       {
174          if((0==strcmp("EggDBusChanged", dbus_message_get_member(message))))
175          {
176             DBusMessageIter array;
177             DBusMessageIter dict;
178             DBusMessageIter variant;
179
180             char* dictString = NULL;
181             int value = 0;
182
183             dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
184             dbus_message_iter_get_basic(&dict, &dictString);
185
186             dbus_message_iter_open_container(&dict,DBUS_TYPE_VARIANT, NULL, &variant);
187             dbus_message_iter_get_basic(&dict, &value);
188
189             dbus_message_iter_close_container(&dict, &variant);
190             dbus_message_iter_close_container(&array, &dict);
191
192             // to do handle signal
193             result = DBUS_HANDLER_RESULT_HANDLED;
194          }
195          else
196          {
197             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback -> unknown property:"), DLT_STRING(dbus_message_get_interface(message)) );
198          }
199       }
200       else
201       {
202          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback -> not a signal:"), DLT_STRING(dbus_message_get_member(message)) );
203       }
204    }
205
206    return result;
207 }
208
209
210
211 static void  unregisterObjectPathFallback(DBusConnection *connection, void *user_data)
212 {
213    DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("unregisterObjectPathFallback\n"));
214 }
215
216
217
218 void* run_mainloop(void* dataPtr)
219 {
220    // persistence admin message
221    static const struct DBusObjectPathVTable vtablePersAdmin
222       = {unregisterMessageHandler, checkPersAdminMsg, NULL, };
223
224    // lifecycle message
225    static const struct DBusObjectPathVTable vtableLifecycle
226       = {unregisterMessageHandler, checkLifecycleMsg, NULL, };
227
228    // fallback
229    static const struct DBusObjectPathVTable vtableFallback
230       = {unregisterObjectPathFallback, handleObjectPathMessageFallback, NULL, };
231
232    // setup the dbus
233    mainLoop(vtablePersAdmin, vtableLifecycle, vtableFallback, dataPtr);
234
235    return NULL;
236 }
237
238
239
240 int setup_dbus_mainloop(void)
241 {
242    int rval = 0;
243    pthread_t thread;
244    DBusError err;
245    DBusConnection* conn = NULL;
246
247    const char *pAddress = getenv("PERS_CLIENT_DBUS_ADDRESS");
248
249    // enable locking of data structures in the D-Bus library for multi threading.
250    dbus_threads_init_default();
251
252    dbus_error_init(&err);
253
254    // wain until dbus main loop has been setup and running
255    pthread_mutex_lock(&gDbusInitializedMtx);
256
257    // Connect to the bus and check for errors
258    if(pAddress != NULL)
259    {
260       DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("setup_dbus_mainloop -> Use specific dbus address:"), DLT_STRING(pAddress) );
261
262       conn = dbus_connection_open_private(pAddress, &err);
263
264       if(conn != NULL)
265       {
266          if(!dbus_bus_register(conn, &err))
267          {
268             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("dbus_bus_register() Error :"), DLT_STRING(err.message) );
269             dbus_error_free (&err);
270             return -1;
271          }
272       }
273       else
274       {
275          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("dbus_connection_open_private() Error :"), DLT_STRING(err.message) );
276          dbus_error_free(&err);
277          return -1;
278       }
279    }
280    else
281    {
282       DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("Use default dbus bus (DBUS_BUS_SYSTEM)"));
283
284       conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
285    }
286
287    // create here the dbus connection and pass to main loop
288    rval = pthread_create(&thread, NULL, run_mainloop, conn);
289    if(rval)
290    {
291      DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pthread_create( DBUS run_mainloop ) returned an error:"), DLT_INT(rval) );
292      return -1;
293    }
294
295    // wait for condition variable
296    pthread_cond_wait(&gDbusInitializedCond, &gDbusInitializedMtx);
297
298    pthread_mutex_unlock(&gDbusInitializedMtx);
299    return rval;
300 }
301
302
303
304
305
306 static dbus_bool_t addWatch(DBusWatch *watch, void *data)
307 {
308    dbus_bool_t result = FALSE;
309
310    if (ARRAY_SIZE(gPollInfo.fds)>gPollInfo.nfds)
311    {
312       int flags = dbus_watch_get_flags(watch);
313
314       tObjectEntry * const pEntry = &gPollInfo.objects[gPollInfo.nfds];
315       pEntry->objtype = OT_WATCH;
316       pEntry->watch = watch;
317
318       gPollInfo.fds[gPollInfo.nfds].fd = dbus_watch_get_unix_fd(watch);
319
320       if (TRUE==dbus_watch_get_enabled(watch))
321       {
322          if (flags&DBUS_WATCH_READABLE)
323          {
324             gPollInfo.fds[gPollInfo.nfds].events |= POLLIN;
325          }
326          if (flags&DBUS_WATCH_WRITABLE)
327          {
328             gPollInfo.fds[gPollInfo.nfds].events |= POLLOUT;
329          }
330
331          ++gPollInfo.nfds;
332       }
333
334       result = TRUE;
335    }
336
337    return result;
338 }
339
340
341
342 static void removeWatch(DBusWatch *watch, void *data)
343 {
344    void* w_data = dbus_watch_get_data(watch);
345
346    DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("removeWatch called "), DLT_INT( (int)watch) );
347
348    if(w_data)
349       free(w_data);
350
351    dbus_watch_set_data(watch, NULL, NULL);
352 }
353
354
355
356 static void watchToggled(DBusWatch *watch, void *data)
357 {
358    DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("watchToggled called "), DLT_INT( (int)watch) );
359
360    if(dbus_watch_get_enabled(watch))
361       addWatch(watch, data);
362    else
363       removeWatch(watch, data);
364 }
365
366
367
368 static dbus_bool_t addTimeout(DBusTimeout *timeout, void *data)
369 {
370    dbus_bool_t ret = FALSE;
371
372    if (ARRAY_SIZE(gPollInfo.fds)>gPollInfo.nfds)
373    {
374       const int interval = dbus_timeout_get_interval(timeout);
375       if ((0<interval)&&(TRUE==dbus_timeout_get_enabled(timeout)))
376       {
377          const int tfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
378          if (-1!=tfd)
379          {
380             const struct itimerspec its = { .it_value= {interval/1000, interval%1000} };
381             if (-1!=timerfd_settime(tfd, 0, &its, NULL))
382             {
383                tObjectEntry * const pEntry = &gPollInfo.objects[gPollInfo.nfds];
384                pEntry->objtype = OT_TIMEOUT;
385                pEntry->timeout = timeout;
386                gPollInfo.fds[gPollInfo.nfds].fd = tfd;
387                gPollInfo.fds[gPollInfo.nfds].events |= POLLIN;
388                ++gPollInfo.nfds;
389                ret = TRUE;
390             }
391             else
392             {
393                DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("addTimeout => timerfd_settime() failed"), DLT_STRING(strerror(errno)) );
394             }
395          }
396          else
397          {
398             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("addTimeout => timerfd_create() failed"), DLT_STRING(strerror(errno)) );
399          }
400       }
401    }
402    else
403    {
404       DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("addTimeout => cannot create another fd to be poll()'ed"));
405    }
406
407    return ret;
408 }
409
410
411
412 static void removeTimeout(DBusTimeout *timeout, void *data)
413 {
414
415    int i = gPollInfo.nfds;
416    while ((0<i--)&&(timeout!=gPollInfo.objects[i].timeout));
417
418    if (0<i)
419    {
420       if (-1==close(gPollInfo.fds[i].fd))
421       {
422          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("removeTimeout => close() timerfd"), DLT_STRING(strerror(errno)) );
423       }
424
425       --gPollInfo.nfds;
426       while (gPollInfo.nfds>i)
427       {
428          gPollInfo.fds[i] = gPollInfo.fds[i+1];
429          gPollInfo.objects[i] = gPollInfo.objects[i+1];
430          ++i;
431       }
432
433       gPollInfo.fds[gPollInfo.nfds].fd = -1;
434       gPollInfo.objects[gPollInfo.nfds].objtype = OT_NONE;
435    }
436 }
437
438
439
440 /** callback for libdbus' when timeout changed */
441 static void timeoutToggled(DBusTimeout *timeout, void *data)
442 {
443    int i = gPollInfo.nfds;
444    while ((0<i--)&&(timeout!=gPollInfo.objects[i].timeout));
445    DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("timeoutToggled") );
446    if (0<i)
447    {
448       const int interval = (TRUE==dbus_timeout_get_enabled(timeout))?dbus_timeout_get_interval(timeout):0;
449       const struct itimerspec its = { .it_value= {interval/1000, interval%1000} };
450       if (-1!=timerfd_settime(gPollInfo.fds[i].fd, 0, &its, NULL))
451       {
452          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("timeoutToggled => timerfd_settime()"), DLT_STRING(strerror(errno)) );
453       }
454    }
455 }
456
457
458
459 int mainLoop(DBusObjectPathVTable vtable, DBusObjectPathVTable vtable2,
460              DBusObjectPathVTable vtableFallback, void* userData)
461 {
462    DBusError err;
463    // lock mutex to make sure dbus main loop is running
464    pthread_mutex_lock(&gDbusInitializedMtx);
465
466    DBusConnection* conn = (DBusConnection*)userData;
467    dbus_error_init(&err);
468
469    if (dbus_error_is_set(&err))
470    {
471       DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => Connection Error:"), DLT_STRING(err.message) );
472       dbus_error_free(&err);
473    }
474    else if (NULL != conn)
475    {
476       dbus_connection_set_exit_on_disconnect(conn, FALSE);
477       if (-1 == (gEfds = eventfd(0, EFD_NONBLOCK)))
478       {
479          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => eventfd() failed w/ errno:"), DLT_INT(errno) );
480       }
481       else
482       {
483          int ret;
484          memset(&gPollInfo, 0 , sizeof(gPollInfo));
485
486          gPollInfo.nfds = 1;
487          gPollInfo.fds[0].fd = gEfds;
488          gPollInfo.fds[0].events = POLLIN;
489
490          dbus_bus_add_match(conn, "type='signal',interface='org.genivi.persistence.admin',member='PersistenceModeChanged',path='/org/genivi/persistence/admin'", &err);
491
492          // register for messages
493          if (   (TRUE==dbus_connection_register_object_path(conn, "/org/genivi/persistence/adminconsumer", &vtable, userData))
494              && (TRUE==dbus_connection_register_object_path(conn, "/org/genivi/NodeStateManager/LifeCycleConsumer", &vtable2, userData))
495              && (TRUE==dbus_connection_register_fallback(conn, "/", &vtableFallback, userData)) )
496          {
497             if(   (TRUE!=dbus_connection_set_watch_functions(conn, addWatch, removeWatch, watchToggled, NULL, NULL))
498                || (TRUE!=dbus_connection_set_timeout_functions(conn, addTimeout, removeTimeout, timeoutToggled, NULL, NULL)) )
499             {
500                DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => dbus_connection_set_watch_functions() failed"));
501             }
502             else
503             {
504                pthread_cond_signal(&gDbusInitializedCond);
505                pthread_mutex_unlock(&gDbusInitializedMtx);
506                do
507                {
508                   bContinue = 0; /* assume error */
509
510                   while (DBUS_DISPATCH_DATA_REMAINS==dbus_connection_dispatch(conn));
511
512                   while ((-1==(ret=poll(gPollInfo.fds, gPollInfo.nfds, -1)))&&(EINTR==errno));
513
514                   if (0>ret)
515                   {
516                      DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => poll() failed w/ errno "), DLT_INT(errno) );
517                   }
518                   else if (0==ret)
519                   {
520                      /* poll time-out */
521                   }
522                   else
523                   {
524                      int i;
525
526                      for (i=0; gPollInfo.nfds>i; ++i)
527                      {
528                         /* anything to do */
529                         if (0!=gPollInfo.fds[i].revents)
530                         {
531                            if (OT_TIMEOUT==gPollInfo.objects[i].objtype)
532                            {
533                               /* time-out occured */
534                               unsigned long long nExpCount = 0;
535                               if ((ssize_t)sizeof(nExpCount)!=read(gPollInfo.fds[i].fd, &nExpCount, sizeof(nExpCount)))
536                               {
537                                  DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => read failed"));
538                               }
539                               DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => timeout"));
540
541                               if (FALSE==dbus_timeout_handle(gPollInfo.objects[i].timeout))
542                               {
543                                  DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => dbus_timeout_handle() failed!?"));
544                               }
545                               bContinue = TRUE;
546                            }
547                            else if (gPollInfo.fds[i].fd == gEfds)
548                            {
549                               /* internal command */
550                               if (0!=(gPollInfo.fds[i].revents & POLLIN))
551                               {
552                                  uint16_t buf[64];
553                                  bContinue = TRUE;
554                                  while ((-1==(ret = read(gPollInfo.fds[i].fd, buf, 64)))&&(EINTR == errno));
555                                  if (0>ret)
556                                  {
557                                     DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => read() failed"), DLT_STRING(strerror(errno)) );
558                                     printf(" * mainloop: read F A I L E D\n");
559                                  }
560                                  else if (ret != -1)
561                                  {
562                                     printf(" * mainloop: dispatch command => [0]: %d | [1]: %d | [2]: %d\n", buf[0], buf[1], buf[2]);
563                                     switch (buf[0])
564                                     {
565                                        case CMD_PAS_BLOCK_AND_WRITE_BACK:
566                                           process_block_and_write_data_back((buf[2]), buf[1]);
567                                           break;
568                                        case CMD_LC_PREPARE_SHUTDOWN:
569                                           printf(" CMD => Prepare shutdown\n");
570                                           process_prepare_shutdown((buf[2]), buf[1]);
571                                           break;
572                                        case CMD_SEND_NOTIFY_SIGNAL:
573                                           printf(" CMD => Send notification signal\n");
574                                           process_send_notification_signal(conn);
575                                           break;
576                                        case CMD_REG_NOTIFY_SIGNAL:
577                                           printf(" CMD => Register notification signal\n");
578                                           process_reg_notification_signal(conn);
579                                           break;
580                                        case CMD_SEND_PAS_REQUEST:
581                                           printf(" CMD => Admin request => request: %d | status: %d\n", (buf[2]), buf[1]);
582                                           process_send_pas_request(conn, (buf[2]), buf[1]);
583                                           break;
584                                        case CMD_SEND_PAS_REGISTER:
585                                           printf(" CMD => Admin register => mode: %d | type: %d\n", (buf[2]), buf[1]);
586                                           process_send_pas_register(conn, (buf[1]), buf[2]);
587                                           break;
588                                        case CMD_SEND_LC_REQUEST:
589                                           printf(" CMD => Lifecycle request => request: %d | status\n", (buf[2]), buf[1]);
590                                           process_send_lifecycle_request(conn, (buf[2]), buf[1]);
591                                           break;
592                                        case CMD_SEND_LC_REGISTER:
593                                           printf(" CMD => Lifecycle register => mode: %d | type: %d\n", (buf[2]), buf[1]);
594                                           process_send_lifecycle_register(conn, (buf[1]), buf[2]);
595                                           break;
596                                        case CMD_QUIT:
597                                           bContinue = FALSE;
598                                           break;
599                                        default:
600                                           DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => command not handled"), DLT_INT(buf[0]) );
601                                           break;
602                                     }
603                                  }
604                               }
605                            }
606                            else
607                            {
608                               int flags = 0;
609                               if (0!=(gPollInfo.fds[i].revents & POLLIN))
610                               {
611                                  flags |= DBUS_WATCH_READABLE;
612                               }
613                               if (0!=(gPollInfo.fds[i].revents & POLLOUT))
614                               {
615                                  flags |= DBUS_WATCH_WRITABLE;
616                               }
617                               if (0!=(gPollInfo.fds[i].revents & POLLERR))
618                               {
619                                  flags |= DBUS_WATCH_ERROR;
620                               }
621                               if (0!=(gPollInfo.fds[i].revents & POLLHUP))
622                               {
623                                  flags |= DBUS_WATCH_HANGUP;
624                               }
625
626                               bContinue = dbus_watch_handle(gPollInfo.objects[i].watch, flags);
627                            }
628                         }
629                      }
630                   }
631                }
632                while (0!=bContinue);
633             }
634             dbus_connection_unregister_object_path(conn, "/org/genivi/persistence/adminconsumer");
635             dbus_connection_unregister_object_path(conn, "/org/genivi/NodeStateManager/LifeCycleConsumer");
636             dbus_connection_unregister_object_path(conn, "/");
637          }
638          close(gEfds);
639       }
640       dbus_connection_close(conn);
641       dbus_connection_unref(conn);
642       dbus_shutdown();
643    }
644
645    pthread_cond_signal(&gDbusInitializedCond);
646    pthread_mutex_unlock(&gDbusInitializedMtx);
647    return 0;
648 }
649