~xnox/ubuntu/quantal/lvm2/merge95

« back to all changes in this revision

Viewing changes to .pc/dirs.patch/daemons/dmeventd/dmeventd.c

  • Committer: Dmitrijs Ledkovs
  • Date: 2012-08-15 09:45:58 UTC
  • Revision ID: dmitrijs.ledkovs@canonical.com-20120815094558-1fugetlxzs49g6g9
quilt push

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
 
3
 *
 
4
 * This file is part of the device-mapper userspace tools.
 
5
 *
 
6
 * This copyrighted material is made available to anyone wishing to use,
 
7
 * modify, copy, or redistribute it subject to the terms and conditions
 
8
 * of the GNU Lesser General Public License v.2.1.
 
9
 *
 
10
 * You should have received a copy of the GNU Lesser General Public License
 
11
 * along with this program; if not, write to the Free Software Foundation,
 
12
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
13
 */
 
14
 
 
15
/*
 
16
 * dmeventd - dm event daemon to monitor active mapped devices
 
17
 */
 
18
 
 
19
#define _GNU_SOURCE
 
20
#define _FILE_OFFSET_BITS 64
 
21
 
 
22
#include "configure.h"
 
23
#include "libdevmapper.h"
 
24
#include "libdevmapper-event.h"
 
25
#include "dmeventd.h"
 
26
//#include "libmultilog.h"
 
27
#include "dm-logging.h"
 
28
 
 
29
#include <dlfcn.h>
 
30
#include <errno.h>
 
31
#include <pthread.h>
 
32
#include <sys/file.h>
 
33
#include <sys/stat.h>
 
34
#include <sys/wait.h>
 
35
#include <sys/time.h>
 
36
#include <sys/resource.h>
 
37
#include <unistd.h>
 
38
#include <signal.h>
 
39
#include <arpa/inet.h>          /* for htonl, ntohl */
 
40
 
 
41
#ifdef linux
 
42
#  include <malloc.h>
 
43
 
 
44
/*
 
45
 * Kernel version 2.6.36 and higher has
 
46
 * new OOM killer adjustment interface.
 
47
 */
 
48
#  define OOM_ADJ_FILE_OLD "/proc/self/oom_adj"
 
49
#  define OOM_ADJ_FILE "/proc/self/oom_score_adj"
 
50
 
 
51
/* From linux/oom.h */
 
52
/* Old interface */
 
53
#  define OOM_DISABLE (-17)
 
54
#  define OOM_ADJUST_MIN (-16)
 
55
/* New interface */
 
56
#  define OOM_SCORE_ADJ_MIN (-1000)
 
57
 
 
58
/* Systemd on-demand activation support */
 
59
#  define SD_LISTEN_PID_ENV_VAR_NAME "LISTEN_PID"
 
60
#  define SD_LISTEN_FDS_ENV_VAR_NAME "LISTEN_FDS"
 
61
#  define SD_LISTEN_FDS_START 3
 
62
#  define SD_FD_FIFO_SERVER SD_LISTEN_FDS_START
 
63
#  define SD_FD_FIFO_CLIENT (SD_LISTEN_FDS_START + 1)
 
64
 
 
65
#endif
 
66
 
 
67
/* FIXME We use syslog for now, because multilog is not yet implemented */
 
68
#include <syslog.h>
 
69
 
 
70
static volatile sig_atomic_t _exit_now = 0;     /* set to '1' when signal is given to exit */
 
71
static volatile sig_atomic_t _thread_registries_empty = 1;      /* registries are empty initially */
 
72
 
 
73
/* List (un)link macros. */
 
74
#define LINK(x, head)           dm_list_add(head, &(x)->list)
 
75
#define LINK_DSO(dso)           LINK(dso, &_dso_registry)
 
76
#define LINK_THREAD(thread)     LINK(thread, &_thread_registry)
 
77
 
 
78
#define UNLINK(x)               dm_list_del(&(x)->list)
 
79
#define UNLINK_DSO(x)           UNLINK(x)
 
80
#define UNLINK_THREAD(x)        UNLINK(x)
 
81
 
 
82
#define DAEMON_NAME "dmeventd"
 
83
 
 
84
/*
 
85
  Global mutex for thread list access. Has to be held when:
 
86
  - iterating thread list
 
87
  - adding or removing elements from thread list
 
88
  - changing or reading thread_status's fields:
 
89
    processing, status, events
 
90
  Use _lock_mutex() and _unlock_mutex() to hold/release it
 
91
*/
 
92
static pthread_mutex_t _global_mutex;
 
93
 
 
94
/*
 
95
  There are three states a thread can attain (see struct
 
96
  thread_status, field int status):
 
97
 
 
98
  - DM_THREAD_RUNNING: thread has started up and is either working or
 
99
  waiting for events... transitions to either SHUTDOWN or DONE
 
100
  - DM_THREAD_SHUTDOWN: thread is still doing something, but it is
 
101
  supposed to terminate (and transition to DONE) as soon as it
 
102
  finishes whatever it was doing at the point of flipping state to
 
103
  SHUTDOWN... the thread is still on the thread list
 
104
  - DM_THREAD_DONE: thread has terminated and has been moved over to
 
105
  unused thread list, cleanup pending
 
106
 */
 
107
#define DM_THREAD_RUNNING  0
 
108
#define DM_THREAD_SHUTDOWN 1
 
109
#define DM_THREAD_DONE     2
 
110
 
 
111
#define THREAD_STACK_SIZE (300*1024)
 
112
 
 
113
int dmeventd_debug = 0;
 
114
static int _systemd_activation = 0;
 
115
static int _foreground = 0;
 
116
static int _restart = 0;
 
117
static char **_initial_registrations = 0;
 
118
 
 
119
/* Data kept about a DSO. */
 
120
struct dso_data {
 
121
        struct dm_list list;
 
122
 
 
123
        char *dso_name;         /* DSO name (eg, "evms", "dmraid", "lvm2"). */
 
124
 
 
125
        void *dso_handle;       /* Opaque handle as returned from dlopen(). */
 
126
        unsigned int ref_count; /* Library reference count. */
 
127
 
 
128
        /*
 
129
         * Event processing.
 
130
         *
 
131
         * The DSO can do whatever appropriate steps if an event
 
132
         * happens such as changing the mapping in case a mirror
 
133
         * fails, update the application metadata etc.
 
134
         *
 
135
         * This function gets a dm_task that is a result of
 
136
         * DM_DEVICE_WAITEVENT ioctl (results equivalent to
 
137
         * DM_DEVICE_STATUS). It should not destroy it.
 
138
         * The caller must dispose of the task.
 
139
         */
 
140
        void (*process_event)(struct dm_task *dmt, enum dm_event_mask event, void **user);
 
141
 
 
142
        /*
 
143
         * Device registration.
 
144
         *
 
145
         * When an application registers a device for an event, the DSO
 
146
         * can carry out appropriate steps so that a later call to
 
147
         * the process_event() function is sane (eg, read metadata
 
148
         * and activate a mapping).
 
149
         */
 
150
        int (*register_device)(const char *device, const char *uuid, int major,
 
151
                               int minor, void **user);
 
152
 
 
153
        /*
 
154
         * Device unregistration.
 
155
         *
 
156
         * In case all devices of a mapping (eg, RAID10) are unregistered
 
157
         * for events, the DSO can recognize this and carry out appropriate
 
158
         * steps (eg, deactivate mapping, metadata update).
 
159
         */
 
160
        int (*unregister_device)(const char *device, const char *uuid,
 
161
                                 int major, int minor, void **user);
 
162
};
 
163
static DM_LIST_INIT(_dso_registry);
 
164
 
 
165
/* Structure to keep parsed register variables from client message. */
 
166
struct message_data {
 
167
        char *id;
 
168
        char *dso_name;         /* Name of DSO. */
 
169
        char *device_uuid;      /* Mapped device path. */
 
170
        union {
 
171
                char *str;      /* Events string as fetched from message. */
 
172
                enum dm_event_mask field;       /* Events bitfield. */
 
173
        } events;
 
174
        union {
 
175
                char *str;
 
176
                uint32_t secs;
 
177
        } timeout;
 
178
        struct dm_event_daemon_message *msg;    /* Pointer to message buffer. */
 
179
};
 
180
 
 
181
/*
 
182
 * Housekeeping of thread+device states.
 
183
 *
 
184
 * One thread per mapped device which can block on it until an event
 
185
 * occurs and the event processing function of the DSO gets called.
 
186
 */
 
187
struct thread_status {
 
188
        struct dm_list list;
 
189
 
 
190
        pthread_t thread;
 
191
 
 
192
        struct dso_data *dso_data;      /* DSO this thread accesses. */
 
193
 
 
194
        struct {
 
195
                char *uuid;
 
196
                char *name;
 
197
                int major, minor;
 
198
        } device;
 
199
        uint32_t event_nr;      /* event number */
 
200
        int processing;         /* Set when event is being processed */
 
201
 
 
202
        int status;             /* see DM_THREAD_{RUNNING,SHUTDOWN,DONE}
 
203
                                   constants above */
 
204
        enum dm_event_mask events;      /* bitfield for event filter. */
 
205
        enum dm_event_mask current_events;      /* bitfield for occured events. */
 
206
        struct dm_task *current_task;
 
207
        time_t next_time;
 
208
        uint32_t timeout;
 
209
        struct dm_list timeout_list;
 
210
        void *dso_private; /* dso per-thread status variable */
 
211
};
 
212
static DM_LIST_INIT(_thread_registry);
 
213
static DM_LIST_INIT(_thread_registry_unused);
 
214
 
 
215
static int _timeout_running;
 
216
static DM_LIST_INIT(_timeout_registry);
 
217
static pthread_mutex_t _timeout_mutex = PTHREAD_MUTEX_INITIALIZER;
 
218
static pthread_cond_t _timeout_cond = PTHREAD_COND_INITIALIZER;
 
219
 
 
220
/* Allocate/free the status structure for a monitoring thread. */
 
221
static struct thread_status *_alloc_thread_status(struct message_data *data,
 
222
                                                  struct dso_data *dso_data)
 
223
{
 
224
        struct thread_status *ret = (typeof(ret)) dm_zalloc(sizeof(*ret));
 
225
 
 
226
        if (!ret)
 
227
                return NULL;
 
228
 
 
229
        if (!(ret->device.uuid = dm_strdup(data->device_uuid))) {
 
230
                dm_free(ret);
 
231
                return NULL;
 
232
        }
 
233
 
 
234
        ret->current_task = NULL;
 
235
        ret->device.name = NULL;
 
236
        ret->device.major = ret->device.minor = 0;
 
237
        ret->dso_data = dso_data;
 
238
        ret->events = data->events.field;
 
239
        ret->timeout = data->timeout.secs;
 
240
        dm_list_init(&ret->timeout_list);
 
241
 
 
242
        return ret;
 
243
}
 
244
 
 
245
static void _lib_put(struct dso_data *data);
 
246
static void _free_thread_status(struct thread_status *thread)
 
247
{
 
248
        _lib_put(thread->dso_data);
 
249
        if (thread->current_task)
 
250
                dm_task_destroy(thread->current_task);
 
251
        dm_free(thread->device.uuid);
 
252
        dm_free(thread->device.name);
 
253
        dm_free(thread);
 
254
}
 
255
 
 
256
/* Allocate/free DSO data. */
 
257
static struct dso_data *_alloc_dso_data(struct message_data *data)
 
258
{
 
259
        struct dso_data *ret = (typeof(ret)) dm_zalloc(sizeof(*ret));
 
260
 
 
261
        if (!ret)
 
262
                return NULL;
 
263
 
 
264
        if (!(ret->dso_name = dm_strdup(data->dso_name))) {
 
265
                dm_free(ret);
 
266
                return NULL;
 
267
        }
 
268
 
 
269
        return ret;
 
270
}
 
271
 
 
272
/* Create a device monitoring thread. */
 
273
static int _pthread_create_smallstack(pthread_t *t, void *(*fun)(void *), void *arg)
 
274
{
 
275
        pthread_attr_t attr;
 
276
        pthread_attr_init(&attr);
 
277
        /*
 
278
         * We use a smaller stack since it gets preallocated in its entirety
 
279
         */
 
280
        pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
 
281
        return pthread_create(t, &attr, fun, arg);
 
282
}
 
283
 
 
284
static void _free_dso_data(struct dso_data *data)
 
285
{
 
286
        dm_free(data->dso_name);
 
287
        dm_free(data);
 
288
}
 
289
 
 
290
/*
 
291
 * Fetch a string off src and duplicate it into *ptr.
 
292
 * Pay attention to zero-length strings.
 
293
 */
 
294
/* FIXME? move to libdevmapper to share with the client lib (need to
 
295
   make delimiter a parameter then) */
 
296
static int _fetch_string(char **ptr, char **src, const int delimiter)
 
297
{
 
298
        int ret = 0;
 
299
        char *p;
 
300
        size_t len;
 
301
 
 
302
        if ((p = strchr(*src, delimiter)))
 
303
                *p = 0;
 
304
 
 
305
        if ((*ptr = dm_strdup(*src))) {
 
306
                if ((len = strlen(*ptr)))
 
307
                        *src += len;
 
308
                else {
 
309
                        dm_free(*ptr);
 
310
                        *ptr = NULL;
 
311
                }
 
312
 
 
313
                (*src)++;
 
314
                ret = 1;
 
315
        }
 
316
 
 
317
        if (p)
 
318
                *p = delimiter;
 
319
 
 
320
        return ret;
 
321
}
 
322
 
 
323
/* Free message memory. */
 
324
static void _free_message(struct message_data *message_data)
 
325
{
 
326
        dm_free(message_data->id);
 
327
        dm_free(message_data->dso_name);
 
328
 
 
329
        dm_free(message_data->device_uuid);
 
330
 
 
331
}
 
332
 
 
333
/* Parse a register message from the client. */
 
334
static int _parse_message(struct message_data *message_data)
 
335
{
 
336
        int ret = 0;
 
337
        char *p = message_data->msg->data;
 
338
        struct dm_event_daemon_message *msg = message_data->msg;
 
339
 
 
340
        if (!msg->data)
 
341
                return 0;
 
342
 
 
343
        /*
 
344
         * Retrieve application identifier, mapped device
 
345
         * path and events # string from message.
 
346
         */
 
347
        if (_fetch_string(&message_data->id, &p, ' ') &&
 
348
            _fetch_string(&message_data->dso_name, &p, ' ') &&
 
349
            _fetch_string(&message_data->device_uuid, &p, ' ') &&
 
350
            _fetch_string(&message_data->events.str, &p, ' ') &&
 
351
            _fetch_string(&message_data->timeout.str, &p, ' ')) {
 
352
                if (message_data->events.str) {
 
353
                        enum dm_event_mask i = atoi(message_data->events.str);
 
354
 
 
355
                        /*
 
356
                         * Free string representaion of events.
 
357
                         * Not needed an more.
 
358
                         */
 
359
                        dm_free(message_data->events.str);
 
360
                        message_data->events.field = i;
 
361
                }
 
362
                if (message_data->timeout.str) {
 
363
                        uint32_t secs = atoi(message_data->timeout.str);
 
364
                        dm_free(message_data->timeout.str);
 
365
                        message_data->timeout.secs = secs ? secs :
 
366
                            DM_EVENT_DEFAULT_TIMEOUT;
 
367
                }
 
368
 
 
369
                ret = 1;
 
370
        }
 
371
 
 
372
        dm_free(msg->data);
 
373
        msg->data = NULL;
 
374
        msg->size = 0;
 
375
        return ret;
 
376
};
 
377
 
 
378
/* Global mutex to lock access to lists et al. See _global_mutex
 
379
   above. */
 
380
static int _lock_mutex(void)
 
381
{
 
382
        return pthread_mutex_lock(&_global_mutex);
 
383
}
 
384
 
 
385
static int _unlock_mutex(void)
 
386
{
 
387
        return pthread_mutex_unlock(&_global_mutex);
 
388
}
 
389
 
 
390
/* Check, if a device exists. */
 
391
static int _fill_device_data(struct thread_status *ts)
 
392
{
 
393
        struct dm_task *dmt;
 
394
        struct dm_info dmi;
 
395
 
 
396
        if (!ts->device.uuid)
 
397
                return 0;
 
398
 
 
399
        ts->device.name = NULL;
 
400
        ts->device.major = ts->device.minor = 0;
 
401
 
 
402
        dmt = dm_task_create(DM_DEVICE_INFO);
 
403
        if (!dmt)
 
404
                return 0;
 
405
 
 
406
        if (!dm_task_set_uuid(dmt, ts->device.uuid))
 
407
                goto fail;
 
408
 
 
409
        if (!dm_task_run(dmt))
 
410
                goto fail;
 
411
 
 
412
        ts->device.name = dm_strdup(dm_task_get_name(dmt));
 
413
        if (!ts->device.name)
 
414
                goto fail;
 
415
 
 
416
        if (!dm_task_get_info(dmt, &dmi))
 
417
                goto fail;
 
418
 
 
419
        ts->device.major = dmi.major;
 
420
        ts->device.minor = dmi.minor;
 
421
 
 
422
        dm_task_destroy(dmt);
 
423
        return 1;
 
424
 
 
425
      fail:
 
426
        dm_task_destroy(dmt);
 
427
        dm_free(ts->device.name);
 
428
        return 0;
 
429
}
 
430
 
 
431
/*
 
432
 * Find an existing thread for a device.
 
433
 *
 
434
 * Mutex must be held when calling this.
 
435
 */
 
436
static struct thread_status *_lookup_thread_status(struct message_data *data)
 
437
{
 
438
        struct thread_status *thread;
 
439
 
 
440
        dm_list_iterate_items(thread, &_thread_registry)
 
441
            if (!strcmp(data->device_uuid, thread->device.uuid))
 
442
                return thread;
 
443
 
 
444
        return NULL;
 
445
}
 
446
 
 
447
static int _get_status(struct message_data *message_data)
 
448
{
 
449
        struct dm_event_daemon_message *msg = message_data->msg;
 
450
        struct thread_status *thread;
 
451
        int i, j;
 
452
        int ret = -1;
 
453
        int count = dm_list_size(&_thread_registry);
 
454
        int size = 0, current = 0;
 
455
        char *buffers[count];
 
456
        char *message;
 
457
 
 
458
        dm_free(msg->data);
 
459
 
 
460
        for (i = 0; i < count; ++i)
 
461
                buffers[i] = NULL;
 
462
 
 
463
        i = 0;
 
464
        _lock_mutex();
 
465
        dm_list_iterate_items(thread, &_thread_registry) {
 
466
                if ((current = dm_asprintf(buffers + i, "0:%d %s %s %u %" PRIu32 ";",
 
467
                                           i, thread->dso_data->dso_name,
 
468
                                           thread->device.uuid, thread->events,
 
469
                                           thread->timeout)) < 0) {
 
470
                        _unlock_mutex();
 
471
                        goto out;
 
472
                }
 
473
                ++ i;
 
474
                size += current;
 
475
        }
 
476
        _unlock_mutex();
 
477
 
 
478
        msg->size = size + strlen(message_data->id) + 1;
 
479
        msg->data = dm_malloc(msg->size);
 
480
        if (!msg->data)
 
481
                goto out;
 
482
        *msg->data = 0;
 
483
 
 
484
        message = msg->data;
 
485
        strcpy(message, message_data->id);
 
486
        message += strlen(message_data->id);
 
487
        *message = ' ';
 
488
        message ++;
 
489
        for (j = 0; j < i; ++j) {
 
490
                strcpy(message, buffers[j]);
 
491
                message += strlen(buffers[j]);
 
492
        }
 
493
 
 
494
        ret = 0;
 
495
 out:
 
496
        for (j = 0; j < i; ++j)
 
497
                dm_free(buffers[j]);
 
498
        return ret;
 
499
 
 
500
}
 
501
 
 
502
/* Cleanup at exit. */
 
503
static void _exit_dm_lib(void)
 
504
{
 
505
        dm_lib_release();
 
506
        dm_lib_exit();
 
507
}
 
508
 
 
509
static void _exit_timeout(void *unused __attribute__((unused)))
 
510
{
 
511
        _timeout_running = 0;
 
512
        pthread_mutex_unlock(&_timeout_mutex);
 
513
}
 
514
 
 
515
/* Wake up monitor threads every so often. */
 
516
static void *_timeout_thread(void *unused __attribute__((unused)))
 
517
{
 
518
        struct timespec timeout;
 
519
        time_t curr_time;
 
520
 
 
521
        timeout.tv_nsec = 0;
 
522
        pthread_cleanup_push(_exit_timeout, NULL);
 
523
        pthread_mutex_lock(&_timeout_mutex);
 
524
 
 
525
        while (!dm_list_empty(&_timeout_registry)) {
 
526
                struct thread_status *thread;
 
527
 
 
528
                timeout.tv_sec = 0;
 
529
                curr_time = time(NULL);
 
530
 
 
531
                dm_list_iterate_items_gen(thread, &_timeout_registry, timeout_list) {
 
532
                        if (thread->next_time <= curr_time) {
 
533
                                thread->next_time = curr_time + thread->timeout;
 
534
                                pthread_kill(thread->thread, SIGALRM);
 
535
                        }
 
536
 
 
537
                        if (thread->next_time < timeout.tv_sec || !timeout.tv_sec)
 
538
                                timeout.tv_sec = thread->next_time;
 
539
                }
 
540
 
 
541
                pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex,
 
542
                                       &timeout);
 
543
        }
 
544
 
 
545
        pthread_cleanup_pop(1);
 
546
 
 
547
        return NULL;
 
548
}
 
549
 
 
550
static int _register_for_timeout(struct thread_status *thread)
 
551
{
 
552
        int ret = 0;
 
553
 
 
554
        pthread_mutex_lock(&_timeout_mutex);
 
555
 
 
556
        thread->next_time = time(NULL) + thread->timeout;
 
557
 
 
558
        if (dm_list_empty(&thread->timeout_list)) {
 
559
                dm_list_add(&_timeout_registry, &thread->timeout_list);
 
560
                if (_timeout_running)
 
561
                        pthread_cond_signal(&_timeout_cond);
 
562
        }
 
563
 
 
564
        if (!_timeout_running) {
 
565
                pthread_t timeout_id;
 
566
 
 
567
                if (!(ret = -_pthread_create_smallstack(&timeout_id, _timeout_thread, NULL)))
 
568
                        _timeout_running = 1;
 
569
        }
 
570
 
 
571
        pthread_mutex_unlock(&_timeout_mutex);
 
572
 
 
573
        return ret;
 
574
}
 
575
 
 
576
static void _unregister_for_timeout(struct thread_status *thread)
 
577
{
 
578
        pthread_mutex_lock(&_timeout_mutex);
 
579
        if (!dm_list_empty(&thread->timeout_list)) {
 
580
                dm_list_del(&thread->timeout_list);
 
581
                dm_list_init(&thread->timeout_list);
 
582
        }
 
583
        pthread_mutex_unlock(&_timeout_mutex);
 
584
}
 
585
 
 
586
__attribute__((format(printf, 4, 5)))
 
587
static void _no_intr_log(int level, const char *file, int line,
 
588
                        const char *f, ...)
 
589
{
 
590
        va_list ap;
 
591
 
 
592
        if (errno == EINTR)
 
593
                return;
 
594
        if (level > _LOG_WARN)
 
595
                return;
 
596
 
 
597
        va_start(ap, f);
 
598
 
 
599
        if (level < _LOG_WARN)
 
600
                vfprintf(stderr, f, ap);
 
601
        else
 
602
                vprintf(f, ap);
 
603
 
 
604
        va_end(ap);
 
605
 
 
606
        if (level < _LOG_WARN)
 
607
                fprintf(stderr, "\n");
 
608
        else
 
609
                fprintf(stdout, "\n");
 
610
}
 
611
 
 
612
static sigset_t _unblock_sigalrm(void)
 
613
{
 
614
        sigset_t set, old;
 
615
 
 
616
        sigemptyset(&set);
 
617
        sigaddset(&set, SIGALRM);
 
618
        pthread_sigmask(SIG_UNBLOCK, &set, &old);
 
619
        return old;
 
620
}
 
621
 
 
622
#define DM_WAIT_RETRY 0
 
623
#define DM_WAIT_INTR 1
 
624
#define DM_WAIT_FATAL 2
 
625
 
 
626
/* Wait on a device until an event occurs. */
 
627
static int _event_wait(struct thread_status *thread, struct dm_task **task)
 
628
{
 
629
        sigset_t set;
 
630
        int ret = DM_WAIT_RETRY;
 
631
        struct dm_task *dmt;
 
632
        struct dm_info info;
 
633
 
 
634
        *task = 0;
 
635
 
 
636
        if (!(dmt = dm_task_create(DM_DEVICE_WAITEVENT)))
 
637
                return DM_WAIT_RETRY;
 
638
 
 
639
        thread->current_task = dmt;
 
640
 
 
641
        if (!dm_task_set_uuid(dmt, thread->device.uuid) ||
 
642
            !dm_task_set_event_nr(dmt, thread->event_nr))
 
643
                goto out;
 
644
 
 
645
        /*
 
646
         * This is so that you can break out of waiting on an event,
 
647
         * either for a timeout event, or to cancel the thread.
 
648
         */
 
649
        set = _unblock_sigalrm();
 
650
        dm_log_init(_no_intr_log);
 
651
        errno = 0;
 
652
        if (dm_task_run(dmt)) {
 
653
                thread->current_events |= DM_EVENT_DEVICE_ERROR;
 
654
                ret = DM_WAIT_INTR;
 
655
 
 
656
                if ((ret = dm_task_get_info(dmt, &info)))
 
657
                        thread->event_nr = info.event_nr;
 
658
        } else if (thread->events & DM_EVENT_TIMEOUT && errno == EINTR) {
 
659
                thread->current_events |= DM_EVENT_TIMEOUT;
 
660
                ret = DM_WAIT_INTR;
 
661
        } else if (thread->status == DM_THREAD_SHUTDOWN && errno == EINTR) {
 
662
                ret = DM_WAIT_FATAL;
 
663
        } else {
 
664
                syslog(LOG_NOTICE, "dm_task_run failed, errno = %d, %s",
 
665
                       errno, strerror(errno));
 
666
                if (errno == ENXIO) {
 
667
                        syslog(LOG_ERR, "%s disappeared, detaching",
 
668
                               thread->device.name);
 
669
                        ret = DM_WAIT_FATAL;
 
670
                }
 
671
        }
 
672
 
 
673
        pthread_sigmask(SIG_SETMASK, &set, NULL);
 
674
        dm_log_init(NULL);
 
675
 
 
676
      out:
 
677
        if (ret == DM_WAIT_FATAL || ret == DM_WAIT_RETRY) {
 
678
                dm_task_destroy(dmt);
 
679
                thread->current_task = NULL;
 
680
        } else
 
681
                *task = dmt;
 
682
 
 
683
        return ret;
 
684
}
 
685
 
 
686
/* Register a device with the DSO. */
 
687
static int _do_register_device(struct thread_status *thread)
 
688
{
 
689
        return thread->dso_data->register_device(thread->device.name,
 
690
                                                 thread->device.uuid,
 
691
                                                 thread->device.major,
 
692
                                                 thread->device.minor,
 
693
                                                 &(thread->dso_private));
 
694
}
 
695
 
 
696
/* Unregister a device with the DSO. */
 
697
static int _do_unregister_device(struct thread_status *thread)
 
698
{
 
699
        return thread->dso_data->unregister_device(thread->device.name,
 
700
                                                   thread->device.uuid,
 
701
                                                   thread->device.major,
 
702
                                                   thread->device.minor,
 
703
                                                   &(thread->dso_private));
 
704
}
 
705
 
 
706
/* Process an event in the DSO. */
 
707
static void _do_process_event(struct thread_status *thread, struct dm_task *task)
 
708
{
 
709
        thread->dso_data->process_event(task, thread->current_events, &(thread->dso_private));
 
710
}
 
711
 
 
712
/* Thread cleanup handler to unregister device. */
 
713
static void _monitor_unregister(void *arg)
 
714
{
 
715
        struct thread_status *thread = arg, *thread_iter;
 
716
 
 
717
        if (!_do_unregister_device(thread))
 
718
                syslog(LOG_ERR, "%s: %s unregister failed\n", __func__,
 
719
                       thread->device.name);
 
720
        if (thread->current_task)
 
721
                dm_task_destroy(thread->current_task);
 
722
        thread->current_task = NULL;
 
723
 
 
724
        _lock_mutex();
 
725
        if (thread->events & DM_EVENT_TIMEOUT) {
 
726
                /* _unregister_for_timeout locks another mutex, we
 
727
                   don't want to deadlock so we release our mutex for
 
728
                   a bit */
 
729
                _unlock_mutex();
 
730
                _unregister_for_timeout(thread);
 
731
                _lock_mutex();
 
732
        }
 
733
        /* we may have been relinked to unused registry since we were
 
734
           called, so check that */
 
735
        dm_list_iterate_items(thread_iter, &_thread_registry_unused)
 
736
                if (thread_iter == thread) {
 
737
                        thread->status = DM_THREAD_DONE;
 
738
                        _unlock_mutex();
 
739
                        return;
 
740
                }
 
741
        thread->status = DM_THREAD_DONE;
 
742
        pthread_mutex_lock(&_timeout_mutex);
 
743
        UNLINK_THREAD(thread);
 
744
        LINK(thread, &_thread_registry_unused);
 
745
        pthread_mutex_unlock(&_timeout_mutex);
 
746
        _unlock_mutex();
 
747
}
 
748
 
 
749
static struct dm_task *_get_device_status(struct thread_status *ts)
 
750
{
 
751
        struct dm_task *dmt = dm_task_create(DM_DEVICE_STATUS);
 
752
 
 
753
        if (!dmt)
 
754
                return NULL;
 
755
 
 
756
        if (!dm_task_set_uuid(dmt, ts->device.uuid)) {
 
757
                dm_task_destroy(dmt);
 
758
                return NULL;
 
759
        }
 
760
 
 
761
        if (!dm_task_run(dmt)) {
 
762
                dm_task_destroy(dmt);
 
763
                return NULL;
 
764
        }
 
765
 
 
766
        return dmt;
 
767
}
 
768
 
 
769
/* Device monitoring thread. */
 
770
static void *_monitor_thread(void *arg)
 
771
{
 
772
        struct thread_status *thread = arg;
 
773
        int wait_error = 0;
 
774
        struct dm_task *task;
 
775
 
 
776
        pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
 
777
        pthread_cleanup_push(_monitor_unregister, thread);
 
778
 
 
779
        /* Wait for do_process_request() to finish its task. */
 
780
        _lock_mutex();
 
781
        thread->status = DM_THREAD_RUNNING;
 
782
        _unlock_mutex();
 
783
 
 
784
        /* Loop forever awaiting/analyzing device events. */
 
785
        while (1) {
 
786
                thread->current_events = 0;
 
787
 
 
788
                wait_error = _event_wait(thread, &task);
 
789
                if (wait_error == DM_WAIT_RETRY)
 
790
                        continue;
 
791
 
 
792
                if (wait_error == DM_WAIT_FATAL)
 
793
                        break;
 
794
 
 
795
                /* Timeout occurred, task is not filled properly.
 
796
                 * We get device status here for processing it in DSO.
 
797
                 */
 
798
                if (wait_error == DM_WAIT_INTR &&
 
799
                    thread->current_events & DM_EVENT_TIMEOUT) {
 
800
                        dm_task_destroy(task);
 
801
                        task = _get_device_status(thread);
 
802
                        /* FIXME: syslog fail here ? */
 
803
                        if (!(thread->current_task = task))
 
804
                                continue;
 
805
                }
 
806
 
 
807
                /*
 
808
                 * We know that wait succeeded and stored a
 
809
                 * pointer to dm_task with device status into task.
 
810
                 */
 
811
 
 
812
                /*
 
813
                 * Check against filter.
 
814
                 *
 
815
                 * If there's current events delivered from _event_wait() AND
 
816
                 * the device got registered for those events AND
 
817
                 * those events haven't been processed yet, call
 
818
                 * the DSO's process_event() handler.
 
819
                 */
 
820
                _lock_mutex();
 
821
                if (thread->status == DM_THREAD_SHUTDOWN) {
 
822
                        _unlock_mutex();
 
823
                        break;
 
824
                }
 
825
                _unlock_mutex();
 
826
 
 
827
                if (thread->events & thread->current_events) {
 
828
                        _lock_mutex();
 
829
                        thread->processing = 1;
 
830
                        _unlock_mutex();
 
831
 
 
832
                        _do_process_event(thread, task);
 
833
                        dm_task_destroy(task);
 
834
                        thread->current_task = NULL;
 
835
 
 
836
                        _lock_mutex();
 
837
                        thread->processing = 0;
 
838
                        _unlock_mutex();
 
839
                } else {
 
840
                        dm_task_destroy(task);
 
841
                        thread->current_task = NULL;
 
842
                }
 
843
        }
 
844
 
 
845
        pthread_cleanup_pop(1);
 
846
 
 
847
        return NULL;
 
848
}
 
849
 
 
850
/* Create a device monitoring thread. */
 
851
static int _create_thread(struct thread_status *thread)
 
852
{
 
853
        return _pthread_create_smallstack(&thread->thread, _monitor_thread, thread);
 
854
}
 
855
 
 
856
static int _terminate_thread(struct thread_status *thread)
 
857
{
 
858
        return pthread_kill(thread->thread, SIGALRM);
 
859
}
 
860
 
 
861
/* DSO reference counting. Call with _global_mutex locked! */
 
862
static void _lib_get(struct dso_data *data)
 
863
{
 
864
        data->ref_count++;
 
865
}
 
866
 
 
867
static void _lib_put(struct dso_data *data)
 
868
{
 
869
        if (!--data->ref_count) {
 
870
                dlclose(data->dso_handle);
 
871
                UNLINK_DSO(data);
 
872
                _free_dso_data(data);
 
873
        }
 
874
}
 
875
 
 
876
/* Find DSO data. */
 
877
static struct dso_data *_lookup_dso(struct message_data *data)
 
878
{
 
879
        struct dso_data *dso_data, *ret = NULL;
 
880
 
 
881
        dm_list_iterate_items(dso_data, &_dso_registry)
 
882
            if (!strcmp(data->dso_name, dso_data->dso_name)) {
 
883
                _lib_get(dso_data);
 
884
                ret = dso_data;
 
885
                break;
 
886
        }
 
887
 
 
888
        return ret;
 
889
}
 
890
 
 
891
/* Lookup DSO symbols we need. */
 
892
static int _lookup_symbol(void *dl, void **symbol, const char *name)
 
893
{
 
894
        if ((*symbol = dlsym(dl, name)))
 
895
                return 1;
 
896
 
 
897
        return 0;
 
898
}
 
899
 
 
900
static int lookup_symbols(void *dl, struct dso_data *data)
 
901
{
 
902
        return _lookup_symbol(dl, (void *) &data->process_event,
 
903
                             "process_event") &&
 
904
            _lookup_symbol(dl, (void *) &data->register_device,
 
905
                          "register_device") &&
 
906
            _lookup_symbol(dl, (void *) &data->unregister_device,
 
907
                          "unregister_device");
 
908
}
 
909
 
 
910
/* Load an application specific DSO. */
 
911
static struct dso_data *_load_dso(struct message_data *data)
 
912
{
 
913
        void *dl;
 
914
        struct dso_data *ret = NULL;
 
915
 
 
916
        if (!(dl = dlopen(data->dso_name, RTLD_NOW))) {
 
917
                const char *dlerr = dlerror();
 
918
                syslog(LOG_ERR, "dmeventd %s dlopen failed: %s", data->dso_name,
 
919
                       dlerr);
 
920
                data->msg->size =
 
921
                    dm_asprintf(&(data->msg->data), "%s %s dlopen failed: %s",
 
922
                                data->id, data->dso_name, dlerr);
 
923
                return NULL;
 
924
        }
 
925
 
 
926
        if (!(ret = _alloc_dso_data(data))) {
 
927
                dlclose(dl);
 
928
                return NULL;
 
929
        }
 
930
 
 
931
        if (!(lookup_symbols(dl, ret))) {
 
932
                _free_dso_data(ret);
 
933
                dlclose(dl);
 
934
                return NULL;
 
935
        }
 
936
 
 
937
        /*
 
938
         * Keep handle to close the library once
 
939
         * we've got no references to it any more.
 
940
         */
 
941
        ret->dso_handle = dl;
 
942
        _lib_get(ret);
 
943
 
 
944
        _lock_mutex();
 
945
        LINK_DSO(ret);
 
946
        _unlock_mutex();
 
947
 
 
948
        return ret;
 
949
}
 
950
 
 
951
/* Return success on daemon active check. */
 
952
static int _active(struct message_data *message_data)
 
953
{
 
954
        return 0;
 
955
}
 
956
 
 
957
/*
 
958
 * Register for an event.
 
959
 *
 
960
 * Only one caller at a time here, because we use
 
961
 * a FIFO and lock it against multiple accesses.
 
962
 */
 
963
static int _register_for_event(struct message_data *message_data)
 
964
{
 
965
        int ret = 0;
 
966
        struct thread_status *thread, *thread_new = NULL;
 
967
        struct dso_data *dso_data;
 
968
 
 
969
        if (!(dso_data = _lookup_dso(message_data)) &&
 
970
            !(dso_data = _load_dso(message_data))) {
 
971
                stack;
 
972
#ifdef ELIBACC
 
973
                ret = -ELIBACC;
 
974
#else
 
975
                ret = -ENODEV;
 
976
#endif
 
977
                goto out;
 
978
        }
 
979
 
 
980
        /* Preallocate thread status struct to avoid deadlock. */
 
981
        if (!(thread_new = _alloc_thread_status(message_data, dso_data))) {
 
982
                stack;
 
983
                ret = -ENOMEM;
 
984
                goto out;
 
985
        }
 
986
 
 
987
        if (!_fill_device_data(thread_new)) {
 
988
                stack;
 
989
                ret = -ENODEV;
 
990
                goto out;
 
991
        }
 
992
 
 
993
        _lock_mutex();
 
994
 
 
995
        /* If creation of timeout thread fails (as it may), we fail
 
996
           here completely. The client is responsible for either
 
997
           retrying later or trying to register without timeout
 
998
           events. However, if timeout thread cannot be started, it
 
999
           usually means we are so starved on resources that we are
 
1000
           almost as good as dead already... */
 
1001
        if (thread_new->events & DM_EVENT_TIMEOUT) {
 
1002
                ret = -_register_for_timeout(thread_new);
 
1003
                if (ret)
 
1004
                        goto outth;
 
1005
        }
 
1006
 
 
1007
        if (!(thread = _lookup_thread_status(message_data))) {
 
1008
                _unlock_mutex();
 
1009
 
 
1010
                if (!(ret = _do_register_device(thread_new)))
 
1011
                        goto out;
 
1012
 
 
1013
                thread = thread_new;
 
1014
                thread_new = NULL;
 
1015
 
 
1016
                /* Try to create the monitoring thread for this device. */
 
1017
                _lock_mutex();
 
1018
                if ((ret = -_create_thread(thread))) {
 
1019
                        _unlock_mutex();
 
1020
                        _do_unregister_device(thread);
 
1021
                        _free_thread_status(thread);
 
1022
                        goto out;
 
1023
                } else
 
1024
                        LINK_THREAD(thread);
 
1025
        }
 
1026
 
 
1027
        /* Or event # into events bitfield. */
 
1028
        thread->events |= message_data->events.field;
 
1029
 
 
1030
    outth:
 
1031
        _unlock_mutex();
 
1032
 
 
1033
      out:
 
1034
        /*
 
1035
         * Deallocate thread status after releasing
 
1036
         * the lock in case we haven't used it.
 
1037
         */
 
1038
        if (thread_new)
 
1039
                _free_thread_status(thread_new);
 
1040
 
 
1041
        return ret;
 
1042
}
 
1043
 
 
1044
/*
 
1045
 * Unregister for an event.
 
1046
 *
 
1047
 * Only one caller at a time here as with register_for_event().
 
1048
 */
 
1049
static int _unregister_for_event(struct message_data *message_data)
 
1050
{
 
1051
        int ret = 0;
 
1052
        struct thread_status *thread;
 
1053
 
 
1054
        /*
 
1055
         * Clear event in bitfield and deactivate
 
1056
         * monitoring thread in case bitfield is 0.
 
1057
         */
 
1058
        _lock_mutex();
 
1059
 
 
1060
        if (!(thread = _lookup_thread_status(message_data))) {
 
1061
                _unlock_mutex();
 
1062
                ret = -ENODEV;
 
1063
                goto out;
 
1064
        }
 
1065
 
 
1066
        if (thread->status == DM_THREAD_DONE) {
 
1067
                /* the thread has terminated while we were not
 
1068
                   watching */
 
1069
                _unlock_mutex();
 
1070
                return 0;
 
1071
        }
 
1072
 
 
1073
        thread->events &= ~message_data->events.field;
 
1074
 
 
1075
        if (!(thread->events & DM_EVENT_TIMEOUT))
 
1076
                _unregister_for_timeout(thread);
 
1077
        /*
 
1078
         * In case there's no events to monitor on this device ->
 
1079
         * unlink and terminate its monitoring thread.
 
1080
         */
 
1081
        if (!thread->events) {
 
1082
                pthread_mutex_lock(&_timeout_mutex);
 
1083
                UNLINK_THREAD(thread);
 
1084
                LINK(thread, &_thread_registry_unused);
 
1085
                pthread_mutex_unlock(&_timeout_mutex);
 
1086
        }
 
1087
        _unlock_mutex();
 
1088
 
 
1089
      out:
 
1090
        return ret;
 
1091
}
 
1092
 
 
1093
/*
 
1094
 * Get registered device.
 
1095
 *
 
1096
 * Only one caller at a time here as with register_for_event().
 
1097
 */
 
1098
static int _registered_device(struct message_data *message_data,
 
1099
                             struct thread_status *thread)
 
1100
{
 
1101
        struct dm_event_daemon_message *msg = message_data->msg;
 
1102
 
 
1103
        const char *fmt = "%s %s %s %u";
 
1104
        const char *id = message_data->id;
 
1105
        const char *dso = thread->dso_data->dso_name;
 
1106
        const char *dev = thread->device.uuid;
 
1107
        int r;
 
1108
        unsigned events = ((thread->status == DM_THREAD_RUNNING)
 
1109
                           && (thread->events)) ? thread->events : thread->
 
1110
            events | DM_EVENT_REGISTRATION_PENDING;
 
1111
 
 
1112
        dm_free(msg->data);
 
1113
 
 
1114
        if ((r = dm_asprintf(&(msg->data), fmt, id, dso, dev, events)) < 0) {
 
1115
                msg->size = 0;
 
1116
                return -ENOMEM;
 
1117
        }
 
1118
 
 
1119
        msg->size = (uint32_t) r;
 
1120
 
 
1121
        return 0;
 
1122
}
 
1123
 
 
1124
static int _want_registered_device(char *dso_name, char *device_uuid,
 
1125
                                  struct thread_status *thread)
 
1126
{
 
1127
        /* If DSO names and device paths are equal. */
 
1128
        if (dso_name && device_uuid)
 
1129
                return !strcmp(dso_name, thread->dso_data->dso_name) &&
 
1130
                    !strcmp(device_uuid, thread->device.uuid) &&
 
1131
                        (thread->status == DM_THREAD_RUNNING ||
 
1132
                         (thread->events & DM_EVENT_REGISTRATION_PENDING));
 
1133
 
 
1134
        /* If DSO names are equal. */
 
1135
        if (dso_name)
 
1136
                return !strcmp(dso_name, thread->dso_data->dso_name) &&
 
1137
                        (thread->status == DM_THREAD_RUNNING ||
 
1138
                         (thread->events & DM_EVENT_REGISTRATION_PENDING));
 
1139
 
 
1140
        /* If device paths are equal. */
 
1141
        if (device_uuid)
 
1142
                return !strcmp(device_uuid, thread->device.uuid) &&
 
1143
                        (thread->status == DM_THREAD_RUNNING ||
 
1144
                         (thread->events & DM_EVENT_REGISTRATION_PENDING));
 
1145
 
 
1146
        return 1;
 
1147
}
 
1148
 
 
1149
static int _get_registered_dev(struct message_data *message_data, int next)
 
1150
{
 
1151
        struct thread_status *thread, *hit = NULL;
 
1152
        int ret = -ENOENT;
 
1153
 
 
1154
        _lock_mutex();
 
1155
 
 
1156
        /* Iterate list of threads checking if we want a particular one. */
 
1157
        dm_list_iterate_items(thread, &_thread_registry)
 
1158
                if (_want_registered_device(message_data->dso_name,
 
1159
                                            message_data->device_uuid,
 
1160
                                            thread)) {
 
1161
                        hit = thread;
 
1162
                        break;
 
1163
                }
 
1164
 
 
1165
        /*
 
1166
         * If we got a registered device and want the next one ->
 
1167
         * fetch next conforming element off the list.
 
1168
         */
 
1169
        if (hit && !next)
 
1170
                goto reg;
 
1171
 
 
1172
        if (!hit)
 
1173
                goto out;
 
1174
 
 
1175
        while (1) {
 
1176
                if (dm_list_end(&_thread_registry, &thread->list))
 
1177
                        goto out;
 
1178
 
 
1179
                thread = dm_list_item(thread->list.n, struct thread_status);
 
1180
                if (_want_registered_device(message_data->dso_name, NULL, thread)) {
 
1181
                        hit = thread;
 
1182
                        break;
 
1183
                }
 
1184
        }
 
1185
 
 
1186
      reg:
 
1187
        ret = _registered_device(message_data, hit);
 
1188
 
 
1189
      out:
 
1190
        _unlock_mutex();
 
1191
 
 
1192
        return ret;
 
1193
}
 
1194
 
 
1195
static int _get_registered_device(struct message_data *message_data)
 
1196
{
 
1197
        return _get_registered_dev(message_data, 0);
 
1198
}
 
1199
 
 
1200
static int _get_next_registered_device(struct message_data *message_data)
 
1201
{
 
1202
        return _get_registered_dev(message_data, 1);
 
1203
}
 
1204
 
 
1205
static int _set_timeout(struct message_data *message_data)
 
1206
{
 
1207
        struct thread_status *thread;
 
1208
 
 
1209
        _lock_mutex();
 
1210
        if ((thread = _lookup_thread_status(message_data)))
 
1211
                thread->timeout = message_data->timeout.secs;
 
1212
        _unlock_mutex();
 
1213
 
 
1214
        return thread ? 0 : -ENODEV;
 
1215
}
 
1216
 
 
1217
static int _get_timeout(struct message_data *message_data)
 
1218
{
 
1219
        struct thread_status *thread;
 
1220
        struct dm_event_daemon_message *msg = message_data->msg;
 
1221
 
 
1222
        dm_free(msg->data);
 
1223
 
 
1224
        _lock_mutex();
 
1225
        if ((thread = _lookup_thread_status(message_data))) {
 
1226
                msg->size =
 
1227
                    dm_asprintf(&(msg->data), "%s %" PRIu32, message_data->id,
 
1228
                                thread->timeout);
 
1229
        } else {
 
1230
                msg->data = NULL;
 
1231
                msg->size = 0;
 
1232
        }
 
1233
        _unlock_mutex();
 
1234
 
 
1235
        return thread ? 0 : -ENODEV;
 
1236
}
 
1237
 
 
1238
/* Initialize a fifos structure with path names. */
 
1239
static void _init_fifos(struct dm_event_fifos *fifos)
 
1240
{
 
1241
        memset(fifos, 0, sizeof(*fifos));
 
1242
 
 
1243
        fifos->client_path = DM_EVENT_FIFO_CLIENT;
 
1244
        fifos->server_path = DM_EVENT_FIFO_SERVER;
 
1245
}
 
1246
 
 
1247
/* Open fifos used for client communication. */
 
1248
static int _open_fifos(struct dm_event_fifos *fifos)
 
1249
{
 
1250
        struct stat st;
 
1251
 
 
1252
        /* Create client fifo. */
 
1253
        (void) dm_prepare_selinux_context(fifos->client_path, S_IFIFO);
 
1254
        if ((mkfifo(fifos->client_path, 0600) == -1) && errno != EEXIST) {
 
1255
                syslog(LOG_ERR, "%s: Failed to create client fifo %s: %m.\n",
 
1256
                       __func__, fifos->client_path);
 
1257
                (void) dm_prepare_selinux_context(NULL, 0);
 
1258
                return 0;
 
1259
        }
 
1260
 
 
1261
        /* Create server fifo. */
 
1262
        (void) dm_prepare_selinux_context(fifos->server_path, S_IFIFO);
 
1263
        if ((mkfifo(fifos->server_path, 0600) == -1) && errno != EEXIST) {
 
1264
                syslog(LOG_ERR, "%s: Failed to create server fifo %s: %m.\n",
 
1265
                       __func__, fifos->server_path);
 
1266
                (void) dm_prepare_selinux_context(NULL, 0);
 
1267
                return 0;
 
1268
        }
 
1269
 
 
1270
        (void) dm_prepare_selinux_context(NULL, 0);
 
1271
 
 
1272
        /* Warn about wrong permissions if applicable */
 
1273
        if ((!stat(fifos->client_path, &st)) && (st.st_mode & 0777) != 0600)
 
1274
                syslog(LOG_WARNING, "Fixing wrong permissions on %s: %m.\n",
 
1275
                       fifos->client_path);
 
1276
 
 
1277
        if ((!stat(fifos->server_path, &st)) && (st.st_mode & 0777) != 0600)
 
1278
                syslog(LOG_WARNING, "Fixing wrong permissions on %s: %m.\n",
 
1279
                       fifos->server_path);
 
1280
 
 
1281
        /* If they were already there, make sure permissions are ok. */
 
1282
        if (chmod(fifos->client_path, 0600)) {
 
1283
                syslog(LOG_ERR, "Unable to set correct file permissions on %s: %m.\n",
 
1284
                       fifos->client_path);
 
1285
                return 0;
 
1286
        }
 
1287
 
 
1288
        if (chmod(fifos->server_path, 0600)) {
 
1289
                syslog(LOG_ERR, "Unable to set correct file permissions on %s: %m.\n",
 
1290
                       fifos->server_path);
 
1291
                return 0;
 
1292
        }
 
1293
 
 
1294
        /* Need to open read+write or we will block or fail */
 
1295
        if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
 
1296
                syslog(LOG_ERR, "Failed to open fifo server %s: %m.\n",
 
1297
                       fifos->server_path);
 
1298
                return 0;
 
1299
        }
 
1300
 
 
1301
        /* Need to open read+write for select() to work. */
 
1302
        if ((fifos->client = open(fifos->client_path, O_RDWR)) < 0) {
 
1303
                syslog(LOG_ERR, "Failed to open fifo client %s: %m", fifos->client_path);
 
1304
                if (close(fifos->server))
 
1305
                        syslog(LOG_ERR, "Failed to close fifo server %s: %m", fifos->server_path);
 
1306
                return 0;
 
1307
        }
 
1308
 
 
1309
        return 1;
 
1310
}
 
1311
 
 
1312
/*
 
1313
 * Read message from client making sure that data is available
 
1314
 * and a complete message is read.  Must not block indefinitely.
 
1315
 */
 
1316
static int _client_read(struct dm_event_fifos *fifos,
 
1317
                       struct dm_event_daemon_message *msg)
 
1318
{
 
1319
        struct timeval t;
 
1320
        unsigned bytes = 0;
 
1321
        int ret = 0;
 
1322
        fd_set fds;
 
1323
        size_t size = 2 * sizeof(uint32_t);     /* status + size */
 
1324
        uint32_t *header = alloca(size);
 
1325
        char *buf = (char *)header;
 
1326
 
 
1327
        msg->data = NULL;
 
1328
 
 
1329
        errno = 0;
 
1330
        while (bytes < size && errno != EOF) {
 
1331
                /* Watch client read FIFO for input. */
 
1332
                FD_ZERO(&fds);
 
1333
                FD_SET(fifos->client, &fds);
 
1334
                t.tv_sec = 1;
 
1335
                t.tv_usec = 0;
 
1336
                ret = select(fifos->client + 1, &fds, NULL, NULL, &t);
 
1337
 
 
1338
                if (!ret && !bytes)     /* nothing to read */
 
1339
                        return 0;
 
1340
 
 
1341
                if (!ret)       /* trying to finish read */
 
1342
                        continue;
 
1343
 
 
1344
                if (ret < 0)    /* error */
 
1345
                        return 0;
 
1346
 
 
1347
                ret = read(fifos->client, buf + bytes, size - bytes);
 
1348
                bytes += ret > 0 ? ret : 0;
 
1349
                if (header && (bytes == 2 * sizeof(uint32_t))) {
 
1350
                        msg->cmd = ntohl(header[0]);
 
1351
                        msg->size = ntohl(header[1]);
 
1352
                        buf = msg->data = dm_malloc(msg->size);
 
1353
                        size = msg->size;
 
1354
                        bytes = 0;
 
1355
                        header = 0;
 
1356
                }
 
1357
        }
 
1358
 
 
1359
        if (bytes != size) {
 
1360
                dm_free(msg->data);
 
1361
                msg->data = NULL;
 
1362
                msg->size = 0;
 
1363
        }
 
1364
 
 
1365
        return bytes == size;
 
1366
}
 
1367
 
 
1368
/*
 
1369
 * Write a message to the client making sure that it is ready to write.
 
1370
 */
 
1371
static int _client_write(struct dm_event_fifos *fifos,
 
1372
                        struct dm_event_daemon_message *msg)
 
1373
{
 
1374
        unsigned bytes = 0;
 
1375
        int ret = 0;
 
1376
        fd_set fds;
 
1377
 
 
1378
        size_t size = 2 * sizeof(uint32_t) + msg->size;
 
1379
        uint32_t *header = alloca(size);
 
1380
        char *buf = (char *)header;
 
1381
 
 
1382
        header[0] = htonl(msg->cmd);
 
1383
        header[1] = htonl(msg->size);
 
1384
        if (msg->data)
 
1385
                memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
 
1386
 
 
1387
        errno = 0;
 
1388
        while (bytes < size && errno != EIO) {
 
1389
                do {
 
1390
                        /* Watch client write FIFO to be ready for output. */
 
1391
                        FD_ZERO(&fds);
 
1392
                        FD_SET(fifos->server, &fds);
 
1393
                } while (select(fifos->server + 1, NULL, &fds, NULL, NULL) !=
 
1394
                         1);
 
1395
 
 
1396
                ret = write(fifos->server, buf + bytes, size - bytes);
 
1397
                bytes += ret > 0 ? ret : 0;
 
1398
        }
 
1399
 
 
1400
        return bytes == size;
 
1401
}
 
1402
 
 
1403
/*
 
1404
 * Handle a client request.
 
1405
 *
 
1406
 * We put the request handling functions into
 
1407
 * a list because of the growing number.
 
1408
 */
 
1409
static int _handle_request(struct dm_event_daemon_message *msg,
 
1410
                          struct message_data *message_data)
 
1411
{
 
1412
        static struct request {
 
1413
                unsigned int cmd;
 
1414
                int (*f)(struct message_data *);
 
1415
        } requests[] = {
 
1416
                { DM_EVENT_CMD_REGISTER_FOR_EVENT, _register_for_event},
 
1417
                { DM_EVENT_CMD_UNREGISTER_FOR_EVENT, _unregister_for_event},
 
1418
                { DM_EVENT_CMD_GET_REGISTERED_DEVICE, _get_registered_device},
 
1419
                { DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
 
1420
                        _get_next_registered_device},
 
1421
                { DM_EVENT_CMD_SET_TIMEOUT, _set_timeout},
 
1422
                { DM_EVENT_CMD_GET_TIMEOUT, _get_timeout},
 
1423
                { DM_EVENT_CMD_ACTIVE, _active},
 
1424
                { DM_EVENT_CMD_GET_STATUS, _get_status},
 
1425
        }, *req;
 
1426
 
 
1427
        for (req = requests; req < requests + sizeof(requests) / sizeof(struct request); req++)
 
1428
                if (req->cmd == msg->cmd)
 
1429
                        return req->f(message_data);
 
1430
 
 
1431
        return -EINVAL;
 
1432
}
 
1433
 
 
1434
/* Process a request passed from the communication thread. */
 
1435
static int _do_process_request(struct dm_event_daemon_message *msg)
 
1436
{
 
1437
        int ret;
 
1438
        char *answer;
 
1439
        static struct message_data message_data;
 
1440
 
 
1441
        /* Parse the message. */
 
1442
        memset(&message_data, 0, sizeof(message_data));
 
1443
        message_data.msg = msg;
 
1444
        if (msg->cmd == DM_EVENT_CMD_HELLO || msg->cmd == DM_EVENT_CMD_DIE)  {
 
1445
                ret = 0;
 
1446
                answer = msg->data;
 
1447
                if (answer) {
 
1448
                        msg->size = dm_asprintf(&(msg->data), "%s %s %d", answer,
 
1449
                                                msg->cmd == DM_EVENT_CMD_DIE ? "DYING" : "HELLO",
 
1450
                                                DM_EVENT_PROTOCOL_VERSION);
 
1451
                        dm_free(answer);
 
1452
                } else {
 
1453
                        msg->size = 0;
 
1454
                        msg->data = NULL;
 
1455
                }
 
1456
        } else if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) {
 
1457
                stack;
 
1458
                ret = -EINVAL;
 
1459
        } else
 
1460
                ret = _handle_request(msg, &message_data);
 
1461
 
 
1462
        msg->cmd = ret;
 
1463
        if (!msg->data)
 
1464
                msg->size = dm_asprintf(&(msg->data), "%s %s", message_data.id, strerror(-ret));
 
1465
 
 
1466
        _free_message(&message_data);
 
1467
 
 
1468
        return ret;
 
1469
}
 
1470
 
 
1471
/* Only one caller at a time. */
 
1472
static void _process_request(struct dm_event_fifos *fifos)
 
1473
{
 
1474
        int die = 0;
 
1475
        struct dm_event_daemon_message msg;
 
1476
 
 
1477
        memset(&msg, 0, sizeof(msg));
 
1478
 
 
1479
        /*
 
1480
         * Read the request from the client (client_read, client_write
 
1481
         * give true on success and false on failure).
 
1482
         */
 
1483
        if (!_client_read(fifos, &msg))
 
1484
                return;
 
1485
 
 
1486
        if (msg.cmd == DM_EVENT_CMD_DIE)
 
1487
                die = 1;
 
1488
 
 
1489
        /* _do_process_request fills in msg (if memory allows for
 
1490
           data, otherwise just cmd and size = 0) */
 
1491
        _do_process_request(&msg);
 
1492
 
 
1493
        if (!_client_write(fifos, &msg))
 
1494
                stack;
 
1495
 
 
1496
        dm_free(msg.data);
 
1497
 
 
1498
        if (die) raise(9);
 
1499
}
 
1500
 
 
1501
static void _process_initial_registrations(void)
 
1502
{
 
1503
        int i = 0;
 
1504
        char *reg;
 
1505
        struct dm_event_daemon_message msg = { 0, 0, NULL };
 
1506
 
 
1507
        while ((reg = _initial_registrations[i])) {
 
1508
                msg.cmd = DM_EVENT_CMD_REGISTER_FOR_EVENT;
 
1509
                if ((msg.size = strlen(reg))) {
 
1510
                        msg.data = reg;
 
1511
                        _do_process_request(&msg);
 
1512
                }
 
1513
                ++ i;
 
1514
        }
 
1515
}
 
1516
 
 
1517
static void _cleanup_unused_threads(void)
 
1518
{
 
1519
        int ret;
 
1520
        struct dm_list *l;
 
1521
        struct thread_status *thread;
 
1522
        int join_ret = 0;
 
1523
 
 
1524
        _lock_mutex();
 
1525
        while ((l = dm_list_first(&_thread_registry_unused))) {
 
1526
                thread = dm_list_item(l, struct thread_status);
 
1527
                if (thread->processing)
 
1528
                        break;  /* cleanup on the next round */
 
1529
 
 
1530
                if (thread->status == DM_THREAD_RUNNING) {
 
1531
                        thread->status = DM_THREAD_SHUTDOWN;
 
1532
                        break;
 
1533
                }
 
1534
 
 
1535
                if (thread->status == DM_THREAD_SHUTDOWN) {
 
1536
                        if (!thread->events) {
 
1537
                                /* turn codes negative -- should we be returning this? */
 
1538
                                ret = _terminate_thread(thread);
 
1539
 
 
1540
                                if (ret == ESRCH) {
 
1541
                                        thread->status = DM_THREAD_DONE;
 
1542
                                } else if (ret) {
 
1543
                                        syslog(LOG_ERR,
 
1544
                                               "Unable to terminate thread: %s\n",
 
1545
                                               strerror(-ret));
 
1546
                                        stack;
 
1547
                                }
 
1548
                                break;
 
1549
                        }
 
1550
 
 
1551
                        dm_list_del(l);
 
1552
                        syslog(LOG_ERR,
 
1553
                               "thread can't be on unused list unless !thread->events");
 
1554
                        thread->status = DM_THREAD_RUNNING;
 
1555
                        LINK_THREAD(thread);
 
1556
 
 
1557
                        continue;
 
1558
                }
 
1559
 
 
1560
                if (thread->status == DM_THREAD_DONE) {
 
1561
                        dm_list_del(l);
 
1562
                        join_ret = pthread_join(thread->thread, NULL);
 
1563
                        _free_thread_status(thread);
 
1564
                }
 
1565
        }
 
1566
 
 
1567
        _unlock_mutex();
 
1568
 
 
1569
        if (join_ret)
 
1570
                syslog(LOG_ERR, "Failed pthread_join: %s\n", strerror(join_ret));
 
1571
}
 
1572
 
 
1573
static void _sig_alarm(int signum __attribute__((unused)))
 
1574
{
 
1575
        pthread_testcancel();
 
1576
}
 
1577
 
 
1578
/* Init thread signal handling. */
 
1579
static void _init_thread_signals(void)
 
1580
{
 
1581
        sigset_t my_sigset;
 
1582
        struct sigaction act;
 
1583
 
 
1584
        memset(&act, 0, sizeof(act));
 
1585
        act.sa_handler = _sig_alarm;
 
1586
        sigaction(SIGALRM, &act, NULL);
 
1587
        sigfillset(&my_sigset);
 
1588
 
 
1589
        /* These are used for exiting */
 
1590
        sigdelset(&my_sigset, SIGTERM);
 
1591
        sigdelset(&my_sigset, SIGINT);
 
1592
        sigdelset(&my_sigset, SIGHUP);
 
1593
        sigdelset(&my_sigset, SIGQUIT);
 
1594
 
 
1595
        pthread_sigmask(SIG_BLOCK, &my_sigset, NULL);
 
1596
}
 
1597
 
 
1598
/*
 
1599
 * exit_handler
 
1600
 * @sig
 
1601
 *
 
1602
 * Set the global variable which the process should
 
1603
 * be watching to determine when to exit.
 
1604
 */
 
1605
static void _exit_handler(int sig __attribute__((unused)))
 
1606
{
 
1607
        /*
 
1608
         * We exit when '_exit_now' is set.
 
1609
         * That is, when a signal has been received.
 
1610
         *
 
1611
         * We can not simply set '_exit_now' unless all
 
1612
         * threads are done processing.
 
1613
         */
 
1614
        if (!_thread_registries_empty) {
 
1615
                syslog(LOG_ERR, "There are still devices being monitored.");
 
1616
                syslog(LOG_ERR, "Refusing to exit.");
 
1617
        } else
 
1618
                _exit_now = 1;
 
1619
 
 
1620
}
 
1621
 
 
1622
#ifdef linux
 
1623
static int _set_oom_adj(const char *oom_adj_path, int val)
 
1624
{
 
1625
        FILE *fp;
 
1626
 
 
1627
        if (!(fp = fopen(oom_adj_path, "w"))) {
 
1628
                perror("oom_adj: fopen failed");
 
1629
                return 0;
 
1630
        }
 
1631
 
 
1632
        fprintf(fp, "%i", val);
 
1633
 
 
1634
        if (dm_fclose(fp))
 
1635
                perror("oom_adj: fclose failed");
 
1636
 
 
1637
        return 1;
 
1638
}
 
1639
 
 
1640
/*
 
1641
 * Protection against OOM killer if kernel supports it
 
1642
 */
 
1643
static int _protect_against_oom_killer(void)
 
1644
{
 
1645
        struct stat st;
 
1646
 
 
1647
        if (stat(OOM_ADJ_FILE, &st) == -1) {
 
1648
                if (errno != ENOENT)
 
1649
                        perror(OOM_ADJ_FILE ": stat failed");
 
1650
 
 
1651
                /* Try old oom_adj interface as a fallback */
 
1652
                if (stat(OOM_ADJ_FILE_OLD, &st) == -1) {
 
1653
                        if (errno == ENOENT)
 
1654
                                perror(OOM_ADJ_FILE_OLD " not found");
 
1655
                        else
 
1656
                                perror(OOM_ADJ_FILE_OLD ": stat failed");
 
1657
                        return 1;
 
1658
                }
 
1659
 
 
1660
                return _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_DISABLE) ||
 
1661
                       _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_ADJUST_MIN);
 
1662
        }
 
1663
 
 
1664
        return _set_oom_adj(OOM_ADJ_FILE, OOM_SCORE_ADJ_MIN);
 
1665
}
 
1666
 
 
1667
static int _handle_preloaded_fifo(int fd, const char *path)
 
1668
{
 
1669
        struct stat st_fd, st_path;
 
1670
        int flags;
 
1671
 
 
1672
        if ((flags = fcntl(fd, F_GETFD)) < 0)
 
1673
                return 0;
 
1674
 
 
1675
        if (flags & FD_CLOEXEC)
 
1676
                return 0;
 
1677
 
 
1678
        if (fstat(fd, &st_fd) < 0 || !S_ISFIFO(st_fd.st_mode))
 
1679
                return 0;
 
1680
 
 
1681
        if (stat(path, &st_path) < 0 ||
 
1682
            st_path.st_dev != st_fd.st_dev ||
 
1683
            st_path.st_ino != st_fd.st_ino)
 
1684
                return 0;
 
1685
 
 
1686
        if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
 
1687
                return 0;
 
1688
 
 
1689
        return 1;
 
1690
}
 
1691
 
 
1692
static int _systemd_handover(struct dm_event_fifos *fifos)
 
1693
{
 
1694
        const char *e;
 
1695
        char *p;
 
1696
        unsigned long env_pid, env_listen_fds;
 
1697
        int r = 0;
 
1698
 
 
1699
        memset(fifos, 0, sizeof(*fifos));
 
1700
 
 
1701
        /* LISTEN_PID must be equal to our PID! */
 
1702
        if (!(e = getenv(SD_LISTEN_PID_ENV_VAR_NAME)))
 
1703
                goto out;
 
1704
 
 
1705
        errno = 0;
 
1706
        env_pid = strtoul(e, &p, 10);
 
1707
        if (errno || !p || *p || env_pid <= 0 ||
 
1708
            getpid() != (pid_t) env_pid)
 
1709
                goto out;
 
1710
 
 
1711
        /* LISTEN_FDS must be 2 and the fds must be FIFOSs! */
 
1712
        if (!(e = getenv(SD_LISTEN_FDS_ENV_VAR_NAME)))
 
1713
                goto out;
 
1714
 
 
1715
        errno = 0;
 
1716
        env_listen_fds = strtoul(e, &p, 10);
 
1717
        if (errno || !p || *p || env_listen_fds != 2)
 
1718
                goto out;
 
1719
 
 
1720
        /* Check and handle the FIFOs passed in */
 
1721
        r = (_handle_preloaded_fifo(SD_FD_FIFO_SERVER, DM_EVENT_FIFO_SERVER) &&
 
1722
             _handle_preloaded_fifo(SD_FD_FIFO_CLIENT, DM_EVENT_FIFO_CLIENT));
 
1723
 
 
1724
        if (r) {
 
1725
                fifos->server = SD_FD_FIFO_SERVER;
 
1726
                fifos->server_path = DM_EVENT_FIFO_SERVER;
 
1727
                fifos->client = SD_FD_FIFO_CLIENT;
 
1728
                fifos->client_path = DM_EVENT_FIFO_CLIENT;
 
1729
        }
 
1730
 
 
1731
out:
 
1732
        unsetenv(SD_LISTEN_PID_ENV_VAR_NAME);
 
1733
        unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME);
 
1734
        return r;
 
1735
}
 
1736
#endif
 
1737
 
 
1738
static void remove_lockfile(void)
 
1739
{
 
1740
        if (unlink(DMEVENTD_PIDFILE))
 
1741
                perror(DMEVENTD_PIDFILE ": unlink failed");
 
1742
}
 
1743
 
 
1744
static void _daemonize(void)
 
1745
{
 
1746
        int child_status;
 
1747
        int fd;
 
1748
        pid_t pid;
 
1749
        struct rlimit rlim;
 
1750
        struct timeval tval;
 
1751
        sigset_t my_sigset;
 
1752
 
 
1753
        sigemptyset(&my_sigset);
 
1754
        if (sigprocmask(SIG_SETMASK, &my_sigset, NULL) < 0) {
 
1755
                fprintf(stderr, "Unable to restore signals.\n");
 
1756
                exit(EXIT_FAILURE);
 
1757
        }
 
1758
        signal(SIGTERM, &_exit_handler);
 
1759
 
 
1760
        switch (pid = fork()) {
 
1761
        case -1:
 
1762
                perror("fork failed:");
 
1763
                exit(EXIT_FAILURE);
 
1764
 
 
1765
        case 0:         /* Child */
 
1766
                break;
 
1767
 
 
1768
        default:
 
1769
                /* Wait for response from child */
 
1770
                while (!waitpid(pid, &child_status, WNOHANG) && !_exit_now) {
 
1771
                        tval.tv_sec = 0;
 
1772
                        tval.tv_usec = 250000;  /* .25 sec */
 
1773
                        select(0, NULL, NULL, NULL, &tval);
 
1774
                }
 
1775
 
 
1776
                if (_exit_now)  /* Child has signaled it is ok - we can exit now */
 
1777
                        exit(EXIT_SUCCESS);
 
1778
 
 
1779
                /* Problem with child.  Determine what it is by exit code */
 
1780
                switch (WEXITSTATUS(child_status)) {
 
1781
                case EXIT_DESC_CLOSE_FAILURE:
 
1782
                case EXIT_DESC_OPEN_FAILURE:
 
1783
                case EXIT_FIFO_FAILURE:
 
1784
                case EXIT_CHDIR_FAILURE:
 
1785
                default:
 
1786
                        fprintf(stderr, "Child exited with code %d\n", WEXITSTATUS(child_status));
 
1787
                        break;
 
1788
                }
 
1789
 
 
1790
                exit(WEXITSTATUS(child_status));
 
1791
        }
 
1792
 
 
1793
        if (chdir("/"))
 
1794
                exit(EXIT_CHDIR_FAILURE);
 
1795
 
 
1796
        if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
 
1797
                fd = 256;       /* just have to guess */
 
1798
        else
 
1799
                fd = rlim.rlim_cur;
 
1800
 
 
1801
        for (--fd; fd >= 0; fd--) {
 
1802
#ifdef linux
 
1803
                /* Do not close fds preloaded by systemd! */
 
1804
                if (_systemd_activation &&
 
1805
                    (fd == SD_FD_FIFO_SERVER || fd == SD_FD_FIFO_CLIENT))
 
1806
                        continue;
 
1807
#endif
 
1808
                (void) close(fd);
 
1809
        }
 
1810
 
 
1811
        if ((open("/dev/null", O_RDONLY) < 0) ||
 
1812
            (open("/dev/null", O_WRONLY) < 0) ||
 
1813
            (open("/dev/null", O_WRONLY) < 0))
 
1814
                exit(EXIT_DESC_OPEN_FAILURE);
 
1815
 
 
1816
        setsid();
 
1817
}
 
1818
 
 
1819
static void restart(void)
 
1820
{
 
1821
        struct dm_event_fifos fifos;
 
1822
        struct dm_event_daemon_message msg = { 0, 0, NULL };
 
1823
        int i, count = 0;
 
1824
        char *message;
 
1825
        int length;
 
1826
        int version;
 
1827
 
 
1828
        /* Get the list of registrations from the running daemon. */
 
1829
 
 
1830
        if (!init_fifos(&fifos)) {
 
1831
                fprintf(stderr, "WARNING: Could not initiate communication with existing dmeventd.\n");
 
1832
                return;
 
1833
        }
 
1834
 
 
1835
        if (!dm_event_get_version(&fifos, &version)) {
 
1836
                fprintf(stderr, "WARNING: Could not communicate with existing dmeventd.\n");
 
1837
                fini_fifos(&fifos);
 
1838
                return;
 
1839
        }
 
1840
 
 
1841
        if (version < 1) {
 
1842
                fprintf(stderr, "WARNING: The running dmeventd instance is too old.\n"
 
1843
                                "Protocol version %d (required: 1). Action cancelled.\n",
 
1844
                                version);
 
1845
                exit(EXIT_FAILURE);
 
1846
        }
 
1847
 
 
1848
        if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0)) {
 
1849
                exit(EXIT_FAILURE);
 
1850
        }
 
1851
 
 
1852
        message = msg.data;
 
1853
        message = strchr(message, ' ');
 
1854
        ++ message;
 
1855
        length = strlen(msg.data);
 
1856
        for (i = 0; i < length; ++i) {
 
1857
                if (msg.data[i] == ';') {
 
1858
                        msg.data[i] = 0;
 
1859
                        ++count;
 
1860
                }
 
1861
        }
 
1862
 
 
1863
        if (!(_initial_registrations = dm_malloc(sizeof(char*) * (count + 1)))) {
 
1864
                fprintf(stderr, "Memory allocation registration failed.\n");
 
1865
                exit(EXIT_FAILURE);
 
1866
        }
 
1867
 
 
1868
        for (i = 0; i < count; ++i) {
 
1869
                if (!(_initial_registrations[i] = dm_strdup(message))) {
 
1870
                        fprintf(stderr, "Memory allocation for message failed.\n");
 
1871
                        exit(EXIT_FAILURE);
 
1872
                }
 
1873
                message += strlen(message) + 1;
 
1874
        }
 
1875
        _initial_registrations[count] = 0;
 
1876
 
 
1877
        if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0)) {
 
1878
                fprintf(stderr, "Old dmeventd refused to die.\n");
 
1879
                exit(EXIT_FAILURE);
 
1880
        }
 
1881
 
 
1882
        fini_fifos(&fifos);
 
1883
}
 
1884
 
 
1885
static void usage(char *prog, FILE *file)
 
1886
{
 
1887
        fprintf(file, "Usage:\n"
 
1888
                "%s [-d [-d [-d]]] [-f] [-h] [-R] [-V] [-?]\n\n"
 
1889
                "   -d       Log debug messages to syslog (-d, -dd, -ddd)\n"
 
1890
                "   -f       Don't fork, run in the foreground\n"
 
1891
                "   -h -?    Show this help information\n"
 
1892
                "   -R       Restart dmeventd\n"
 
1893
                "   -V       Show version of dmeventd\n\n", prog);
 
1894
}
 
1895
 
 
1896
int main(int argc, char *argv[])
 
1897
{
 
1898
        signed char opt;
 
1899
        struct dm_event_fifos fifos;
 
1900
        //struct sys_log logdata = {DAEMON_NAME, LOG_DAEMON};
 
1901
 
 
1902
        opterr = 0;
 
1903
        optind = 0;
 
1904
 
 
1905
        while ((opt = getopt(argc, argv, "?fhVdR")) != EOF) {
 
1906
                switch (opt) {
 
1907
                case 'h':
 
1908
                        usage(argv[0], stdout);
 
1909
                        exit(0);
 
1910
                case '?':
 
1911
                        usage(argv[0], stderr);
 
1912
                        exit(0);
 
1913
                case 'R':
 
1914
                        _restart++;
 
1915
                        break;
 
1916
                case 'f':
 
1917
                        _foreground++;
 
1918
                        break;
 
1919
                case 'd':
 
1920
                        dmeventd_debug++;
 
1921
                        break;
 
1922
                case 'V':
 
1923
                        printf("dmeventd version: %s\n", DM_LIB_VERSION);
 
1924
                        exit(1);
 
1925
                }
 
1926
        }
 
1927
 
 
1928
        /*
 
1929
         * Switch to C locale to avoid reading large locale-archive file
 
1930
         * used by some glibc (on some distributions it takes over 100MB).
 
1931
         * Daemon currently needs to use mlockall().
 
1932
         */
 
1933
        if (setenv("LANG", "C", 1))
 
1934
                perror("Cannot set LANG to C");
 
1935
 
 
1936
        if (_restart)
 
1937
                restart();
 
1938
 
 
1939
#ifdef linux
 
1940
        _systemd_activation = _systemd_handover(&fifos);
 
1941
#endif
 
1942
 
 
1943
        if (!_foreground)
 
1944
                _daemonize();
 
1945
 
 
1946
        openlog("dmeventd", LOG_PID, LOG_DAEMON);
 
1947
 
 
1948
        (void) dm_prepare_selinux_context(DMEVENTD_PIDFILE, S_IFREG);
 
1949
        if (dm_create_lockfile(DMEVENTD_PIDFILE) == 0)
 
1950
                exit(EXIT_FAILURE);
 
1951
 
 
1952
        atexit(remove_lockfile);
 
1953
        (void) dm_prepare_selinux_context(NULL, 0);
 
1954
 
 
1955
        /* Set the rest of the signals to cause '_exit_now' to be set */
 
1956
        signal(SIGINT, &_exit_handler);
 
1957
        signal(SIGHUP, &_exit_handler);
 
1958
        signal(SIGQUIT, &_exit_handler);
 
1959
 
 
1960
#ifdef linux
 
1961
        /* Systemd has adjusted oom killer for us already */
 
1962
        if (!_systemd_activation && !_protect_against_oom_killer())
 
1963
                syslog(LOG_ERR, "Failed to protect against OOM killer");
 
1964
#endif
 
1965
 
 
1966
        _init_thread_signals();
 
1967
 
 
1968
        //multilog_clear_logging();
 
1969
        //multilog_add_type(std_syslog, &logdata);
 
1970
        //multilog_init_verbose(std_syslog, _LOG_DEBUG);
 
1971
        //multilog_async(1);
 
1972
 
 
1973
        if (!_systemd_activation)
 
1974
                _init_fifos(&fifos);
 
1975
 
 
1976
        pthread_mutex_init(&_global_mutex, NULL);
 
1977
 
 
1978
        if (!_systemd_activation && !_open_fifos(&fifos))
 
1979
                exit(EXIT_FIFO_FAILURE);
 
1980
 
 
1981
        /* Signal parent, letting them know we are ready to go. */
 
1982
        if (!_foreground)
 
1983
                kill(getppid(), SIGTERM);
 
1984
        syslog(LOG_NOTICE, "dmeventd ready for processing.");
 
1985
 
 
1986
        if (_initial_registrations)
 
1987
                _process_initial_registrations();
 
1988
 
 
1989
        while (!_exit_now) {
 
1990
                _process_request(&fifos);
 
1991
                _cleanup_unused_threads();
 
1992
                _lock_mutex();
 
1993
                if (!dm_list_empty(&_thread_registry)
 
1994
                    || !dm_list_empty(&_thread_registry_unused))
 
1995
                        _thread_registries_empty = 0;
 
1996
                else
 
1997
                        _thread_registries_empty = 1;
 
1998
                _unlock_mutex();
 
1999
        }
 
2000
 
 
2001
        _exit_dm_lib();
 
2002
 
 
2003
        pthread_mutex_destroy(&_global_mutex);
 
2004
 
 
2005
        syslog(LOG_NOTICE, "dmeventd shutting down.");
 
2006
        closelog();
 
2007
 
 
2008
        exit(EXIT_SUCCESS);
 
2009
}