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