Makefile.in: Drop dist target
[secnet] / hackypar.c
CommitLineData
c215a4bc
IJ
1/* Hacky parallelism */
2/*
3 * This file is part of secnet.
4 * See README for full list of copyright holders.
5 *
6 * secnet is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
9c6a8729 8 * the Free Software Foundation; either version 3 of the License, or
c215a4bc
IJ
9 * (at your option) any later version.
10 *
11 * secnet is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * version 3 along with secnet; if not, see
18 * https://www.gnu.org/licenses/gpl.html.
19 */
3b83c932
SE
20
21#define _GNU_SOURCE
22
23#include "secnet.h"
24#include "util.h"
25#include "hackypar.h"
26
27#ifdef HACKY_PARALLEL
28
29#include <stdio.h>
30#include <unistd.h>
31#include <errno.h>
32#include <string.h>
33#include <signal.h>
34#include <assert.h>
35#include <sys/wait.h>
36
37#define HASHSIZE 16
38#define CACHESIZE 16
39
40typedef enum { hp_idle, hp_compute, hp_deferring, hp_fail } HPState;
41
42static HPState state;
43static pid_t child;
44
0902e6e2
IJ
45static void checkchild(void)
46{
47 int r, status;
3b83c932 48
0902e6e2
IJ
49 if (!child) return;
50
51 r= waitpid(child,&status,WNOHANG); if (!r) return;
52 if (r==-1) {
53 Message(M_ERR,"hacky_par: waitpid: %s\n",strerror(errno));
54 return;
55 }
56 child= 0;
3b83c932 57
0902e6e2
IJ
58 if (WIFSIGNALED(status)) {
59 Message(M_ERR,"hacky_par: signaled! %s\n",strsignal(WTERMSIG(status)));
60 } else if (!WIFEXITED(status)) {
61 Message(M_ERR,"hacky_par: unexpected status! %d\n", r);
62 }
3b83c932
SE
63}
64
0902e6e2
IJ
65static HPState start(void)
66{
67 assert(!child);
3b83c932 68
0902e6e2
IJ
69 child= fork();
70 if (child == -1) {
71 Message(M_ERR,"hacky_par: fork failed: %s\n",strerror(errno));
72 return hp_fail;
73 }
3b83c932 74
0902e6e2 75 if (!child) { /* we are the child */
5e7a5e2d 76 afterfork();
0902e6e2
IJ
77 return hp_compute;
78 }
3b83c932 79
0902e6e2
IJ
80 Message(M_INFO,"hacky_par: started, punting\n");
81 return hp_deferring;
3b83c932
SE
82}
83
0902e6e2
IJ
84int hacky_par_start_failnow(void)
85{
86 state= hp_idle;
87 checkchild();
88 if (child) {
89 state= hp_deferring;
90 Message(M_INFO,"hacky_par: busy, punting\n");
91 return 1;
92 }
93 return 0;
3b83c932
SE
94}
95
0902e6e2
IJ
96int hacky_par_mid_failnow(void)
97{
98 state= start();
99 return state != hp_compute;
3b83c932
SE
100}
101
102bool_t (*packy_par_gen)(struct site *st);
103
104void hacky_par_end(int *ok,
4a8aed08 105 int32_t retries, int32_t timeout,
0902e6e2
IJ
106 bool_t (*send_msg)(struct site *st), struct site *st)
107{
108 int i;
3b83c932 109
0902e6e2
IJ
110 switch (state) {
111 case hp_deferring:
112 assert(!*ok);
113 *ok= 1;
114 return;
115 case hp_fail:
116 assert(!*ok);
117 return;
118 case hp_idle:
119 return;
120 case hp_compute:
121 if (!ok) {
122 Message(M_ERR,"hacky_par: compute failed\n");
123 _exit(2);
124 }
125 Message(M_INFO,"hacky_par: got result, sending\n");
126 for (i=1; i<retries; i++) {
127 sleep((timeout + 999)/1000);
128 if (!send_msg(st)) {
129 Message(M_ERR,"hacky_par: retry failed\n");
130 _exit(1);
131 }
3b83c932 132 }
0902e6e2 133 _exit(0);
3b83c932 134 }
3b83c932
SE
135}
136
137#else /*!HACKY_PARALLEL*/
138
139int hacky_par_start_failnow(void) { return 0; }
140int hacky_par_mid_failnow(void) { return 0; }
141void hacky_par_end(int *ok,
4a8aed08 142 int32_t retries, int32_t timeout,
3b83c932
SE
143 bool_t (*send_msg)(struct site *st), struct site *st) { }
144
145#endif /*HACKY_PARALLEL...else*/