torture3: Fix CID 1435119 Error handling issues (CHECKED_RETURN)
[samba.git] / source3 / lib / server_id_watch.c
1 /*
2  * Unix SMB/CIFS implementation.
3  * Wait for process death
4  * Copyright (C) Volker Lendecke 2016
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 #include "replace.h"
21 #include <tevent.h>
22 #include <talloc.h>
23 #include "serverid.h"
24 #include "server_id_watch.h"
25 #include "messages.h"
26 #include "lib/util/tevent_unix.h"
27
28 struct server_id_watch_state {
29         struct tevent_context *ev;
30         struct server_id pid;
31 };
32
33 static void server_id_watch_waited(struct tevent_req *subreq);
34
35 struct tevent_req *server_id_watch_send(TALLOC_CTX *mem_ctx,
36                                         struct tevent_context *ev,
37                                         struct messaging_context *msg,
38                                         struct server_id pid)
39 {
40         struct tevent_req *req, *subreq;
41         struct server_id_watch_state *state;
42
43         req = tevent_req_create(mem_ctx, &state, struct server_id_watch_state);
44         if (req == NULL) {
45                 return NULL;
46         }
47         state->ev = ev;
48         state->pid = pid;
49
50         if (!serverid_exists(&state->pid)) {
51                 tevent_req_done(req);
52                 return tevent_req_post(req, ev);
53         }
54
55         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(0, 500000));
56         if (tevent_req_nomem(subreq, req)) {
57                 return tevent_req_post(req, ev);
58         }
59         tevent_req_set_callback(subreq, server_id_watch_waited, req);
60
61         return req;
62 }
63
64 static void server_id_watch_waited(struct tevent_req *subreq)
65 {
66         struct tevent_req *req = tevent_req_callback_data(
67                 subreq, struct tevent_req);
68         struct server_id_watch_state *state = tevent_req_data(
69                 req, struct server_id_watch_state);
70         bool ok;
71
72         ok = tevent_wakeup_recv(subreq);
73         TALLOC_FREE(subreq);
74         if (!ok) {
75                 tevent_req_oom(req);
76                 return;
77         }
78
79         if (!serverid_exists(&state->pid)) {
80                 tevent_req_done(req);
81                 return;
82         }
83
84         subreq = tevent_wakeup_send(state, state->ev,
85                                     timeval_current_ofs(0, 500000));
86         if (tevent_req_nomem(subreq, req)) {
87                 return;
88         }
89         tevent_req_set_callback(subreq, server_id_watch_waited, req);
90 }
91
92 int server_id_watch_recv(struct tevent_req *req, struct server_id *pid)
93 {
94         struct server_id_watch_state *state = tevent_req_data(
95                 req, struct server_id_watch_state);
96         int err;
97
98         if (tevent_req_is_unix_error(req, &err)) {
99                 return err;
100         }
101         if (pid) {
102                 *pid = state->pid;
103         }
104         return 0;
105 }