2 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
3 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
5 #include "cmogstored.h"
6 static Hash_table
*processes
;
13 static bool process_cmp(const void *_a
, const void *_b
)
15 const struct mog_process
*a
= _a
;
16 const struct mog_process
*b
= _b
;
18 return a
->pid
== b
->pid
;
21 static size_t process_hash(const void *x
, size_t tablesize
)
23 const struct mog_process
*p
= x
;
25 return p
->pid
% tablesize
;
28 /* needed to make valgrind happy */
29 __attribute__((destructor
)) static void process_atexit(void)
35 /* call before forking */
36 void mog_process_init(size_t nr
)
40 processes
= hash_initialize(nr
, NULL
, process_hash
, process_cmp
, free
);
41 mog_oom_if_null(processes
);
44 void mog_process_reset(void)
46 assert(processes
&& "mog_process_init() never called");
47 hash_clear(processes
);
50 char *mog_process_name(unsigned id
)
53 if (mog_process_is_worker(id
))
54 return asprintf(&s
, "worker[%u]", id
) >= 0 ? s
: 0;
57 case MOG_PROC_UNKNOWN
: return 0;
58 case MOG_PROC_IOSTAT
: return strdup("iostat");
59 case MOG_PROC_UPGRADE
: return strdup("upgrade");
62 return asprintf(&s
, "BUG[%u]", id
) >= 0 ? s
: 0;
65 bool mog_process_is_worker(unsigned id
)
68 case MOG_PROC_UNKNOWN
:
70 case MOG_PROC_UPGRADE
:
77 static bool kill_worker(void *ent
, void *k
)
79 struct mog_process
*p
= ent
;
80 struct worker_kill
*wk
= k
;
82 assert(p
->id
!= MOG_PROC_UNKNOWN
&&
83 "MOG_PROC_UNKNOWN should not be registered");
85 if (!mog_process_is_worker(p
->id
))
89 if (kill(p
->pid
, wk
->signal
) == 0)
93 * ESRCH: race between receiving a signal and waitpid(),
94 * ignore the error but count it, so we'lll know to wait on it.
97 syslog(LOG_ERR
, "could not signal worker[%u] pid=%d: %m",
103 * send signal to each worker process, returns number of processes
104 * signalled. (signal=0 counts workers registered)
106 size_t mog_kill_each_worker(int signo
)
108 struct worker_kill wk
= { .signal
= signo
, .count
= 0 };
110 hash_do_for_each(processes
, kill_worker
, &wk
);
112 return (size_t)wk
.count
;
115 /* Registers a process with a given id */
116 void mog_process_register(pid_t pid
, unsigned id
)
118 struct mog_process
*p
= malloc(sizeof(struct mog_process
));
120 assert(id
!= MOG_PROC_UNKNOWN
&&
121 "MOG_PROC_UNKNOWN may not be registered");
129 if (hash_insert(processes
, p
))
130 return; /* success */
132 PRESERVE_ERRNO(free(p
));
134 syslog(LOG_ERR
, "unable to register PID:%d with id=%u: %m",
139 * Call on a pid after a process is reaped, returns the id of the process
140 * Returns MOG_PROC_UNKNOWN if the pid was unknown
142 unsigned mog_process_reaped(pid_t pid
)
144 struct mog_process p
= { .pid
= pid
, .id
= MOG_PROC_UNKNOWN
};
145 struct mog_process
*r
;
147 r
= hash_delete(processes
, &p
);