chiark / gitweb /
NEW etc.: Use NEW at non-formulaic call sites
[secnet] / hackypar.c
CommitLineData
3b83c932
SE
1/* Hacky parallelism; Ian Jackson */
2
3#define _GNU_SOURCE
4
5#include "secnet.h"
6#include "util.h"
7#include "hackypar.h"
8
9#ifdef HACKY_PARALLEL
10
11#include <stdio.h>
12#include <unistd.h>
13#include <errno.h>
14#include <string.h>
15#include <signal.h>
16#include <assert.h>
17#include <sys/wait.h>
18
19#define HASHSIZE 16
20#define CACHESIZE 16
21
22typedef enum { hp_idle, hp_compute, hp_deferring, hp_fail } HPState;
23
24static HPState state;
25static pid_t child;
26
0902e6e2
IJ
27static void checkchild(void)
28{
29 int r, status;
3b83c932 30
0902e6e2
IJ
31 if (!child) return;
32
33 r= waitpid(child,&status,WNOHANG); if (!r) return;
34 if (r==-1) {
35 Message(M_ERR,"hacky_par: waitpid: %s\n",strerror(errno));
36 return;
37 }
38 child= 0;
3b83c932 39
0902e6e2
IJ
40 if (WIFSIGNALED(status)) {
41 Message(M_ERR,"hacky_par: signaled! %s\n",strsignal(WTERMSIG(status)));
42 } else if (!WIFEXITED(status)) {
43 Message(M_ERR,"hacky_par: unexpected status! %d\n", r);
44 }
3b83c932
SE
45}
46
0902e6e2
IJ
47static HPState start(void)
48{
49 assert(!child);
3b83c932 50
0902e6e2
IJ
51 child= fork();
52 if (child == -1) {
53 Message(M_ERR,"hacky_par: fork failed: %s\n",strerror(errno));
54 return hp_fail;
55 }
3b83c932 56
0902e6e2 57 if (!child) { /* we are the child */
5e7a5e2d 58 afterfork();
0902e6e2
IJ
59 return hp_compute;
60 }
3b83c932 61
0902e6e2
IJ
62 Message(M_INFO,"hacky_par: started, punting\n");
63 return hp_deferring;
3b83c932
SE
64}
65
0902e6e2
IJ
66int hacky_par_start_failnow(void)
67{
68 state= hp_idle;
69 checkchild();
70 if (child) {
71 state= hp_deferring;
72 Message(M_INFO,"hacky_par: busy, punting\n");
73 return 1;
74 }
75 return 0;
3b83c932
SE
76}
77
0902e6e2
IJ
78int hacky_par_mid_failnow(void)
79{
80 state= start();
81 return state != hp_compute;
3b83c932
SE
82}
83
84bool_t (*packy_par_gen)(struct site *st);
85
86void hacky_par_end(int *ok,
4a8aed08 87 int32_t retries, int32_t timeout,
0902e6e2
IJ
88 bool_t (*send_msg)(struct site *st), struct site *st)
89{
90 int i;
3b83c932 91
0902e6e2
IJ
92 switch (state) {
93 case hp_deferring:
94 assert(!*ok);
95 *ok= 1;
96 return;
97 case hp_fail:
98 assert(!*ok);
99 return;
100 case hp_idle:
101 return;
102 case hp_compute:
103 if (!ok) {
104 Message(M_ERR,"hacky_par: compute failed\n");
105 _exit(2);
106 }
107 Message(M_INFO,"hacky_par: got result, sending\n");
108 for (i=1; i<retries; i++) {
109 sleep((timeout + 999)/1000);
110 if (!send_msg(st)) {
111 Message(M_ERR,"hacky_par: retry failed\n");
112 _exit(1);
113 }
3b83c932 114 }
0902e6e2 115 _exit(0);
3b83c932 116 }
3b83c932
SE
117}
118
119#else /*!HACKY_PARALLEL*/
120
121int hacky_par_start_failnow(void) { return 0; }
122int hacky_par_mid_failnow(void) { return 0; }
123void hacky_par_end(int *ok,
4a8aed08 124 int32_t retries, int32_t timeout,
3b83c932
SE
125 bool_t (*send_msg)(struct site *st), struct site *st) { }
126
127#endif /*HACKY_PARALLEL...else*/