2 * Unix SMB/CIFS implementation.
3 * Wait for process death
4 * Copyright (C) Volker Lendecke 2016
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "server_id_watch.h"
23 #include "lib/util/server_id.h"
24 #include "lib/util/tevent_unix.h"
25 #include "lib/util/util_file.h"
27 struct server_id_watch_state
{
28 struct tevent_context
*ev
;
35 static void server_id_watch_waited(struct tevent_req
*subreq
);
37 struct tevent_req
*server_id_watch_send(TALLOC_CTX
*mem_ctx
,
38 struct tevent_context
*ev
,
41 struct tevent_req
*req
, *subreq
;
42 struct server_id_watch_state
*state
;
45 req
= tevent_req_create(mem_ctx
, &state
, struct server_id_watch_state
);
51 state
->start
= tevent_timeval_current();
52 state
->warn
= tevent_timeval_add(&state
->start
, 10, 0);
54 state
->debug
= lp_parm_bool(GLOBAL_SECTION_SNUM
,
57 CHECK_DEBUGLVL(DBGLVL_DEBUG
));
59 if (!serverid_exists(&state
->pid
)) {
61 return tevent_req_post(req
, ev
);
64 next
= tevent_timeval_add(&state
->start
, 0, 500000);
65 subreq
= tevent_wakeup_send(state
, ev
, next
);
66 if (tevent_req_nomem(subreq
, req
)) {
67 return tevent_req_post(req
, ev
);
69 tevent_req_set_callback(subreq
, server_id_watch_waited
, req
);
74 static void server_id_watch_waited(struct tevent_req
*subreq
)
76 struct tevent_req
*req
= tevent_req_callback_data(
77 subreq
, struct tevent_req
);
78 struct server_id_watch_state
*state
= tevent_req_data(
79 req
, struct server_id_watch_state
);
84 ok
= tevent_wakeup_recv(subreq
);
91 if (!serverid_exists(&state
->pid
)) {
96 now
= tevent_timeval_current();
102 if (timeval_compare(&state
->warn
, &now
) == -1) {
103 double duration
= timeval_elapsed2(&state
->start
, &now
);
104 const char *cmd
= NULL
;
105 char proc_path
[64] = { 0, };
107 struct server_id_buf buf
;
108 const char *pid
= server_id_str_buf(state
->pid
, &buf
);
111 state
->warn
= tevent_timeval_add(&now
, 10, 0);
113 cmd
= lp_parm_const_string(GLOBAL_SECTION_SNUM
,
123 * Note in a cluster setup pid will be
124 * a NOTE:PID like '1:3978365'
126 * Without clustering it is just '3978365'
128 cmdstr
= talloc_asprintf(state
, "%s %s", cmd
, pid
);
129 if (cmdstr
== NULL
) {
130 DBG_ERR("Process %s hanging for %f seconds?\n"
131 "talloc_asprintf failed\n",
137 ret
= smbrun(cmdstr
, &fd
, NULL
);
140 DBG_ERR("Process %s hanging for %f seconds?\n"
141 "smbrun('%s') failed\n",
142 pid
, duration
, cmdstr
);
147 output
= fd_load(fd
, NULL
, 0, state
);
149 if (output
== NULL
) {
150 DBG_ERR("Process %s hanging for %f seconds?\n"
151 "fd_load() of smbrun('%s') failed\n",
152 pid
, duration
, cmdstr
);
156 DBG_ERR("Process %s hanging for %f seconds?\n"
158 pid
, duration
, cmdstr
, output
);
164 if (!procid_is_local(&state
->pid
) || !sys_have_proc_fds()) {
165 DBG_ERR("Process %s hanging for %f seconds?\n",
170 ret
= snprintf(proc_path
,
171 ARRAY_SIZE(proc_path
),
172 "/proc/%" PRIu64
"/stack",
175 DBG_ERR("Process %s hanging for %f seconds?\n"
182 kstack
= file_load(proc_path
, NULL
, 0, state
);
184 if (kstack
== NULL
) {
185 DBG_ERR("Process %s hanging for %f seconds?\n"
186 "file_load [%s] failed\n",
187 pid
, duration
, proc_path
);
191 DBG_ERR("Process %s hanging for %f seconds?\n"
193 pid
, duration
, proc_path
, kstack
);
198 next
= tevent_timeval_add(&now
, 0, 500000);
199 subreq
= tevent_wakeup_send(state
, state
->ev
, next
);
200 if (tevent_req_nomem(subreq
, req
)) {
203 tevent_req_set_callback(subreq
, server_id_watch_waited
, req
);
206 int server_id_watch_recv(struct tevent_req
*req
, struct server_id
*pid
)
208 struct server_id_watch_state
*state
= tevent_req_data(
209 req
, struct server_id_watch_state
);
212 if (tevent_req_is_unix_error(req
, &err
)) {