comm: Provide udp_socks_deregister
[secnet] / hackypar.c
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
22 typedef enum { hp_idle, hp_compute, hp_deferring, hp_fail } HPState;
23
24 static HPState state;
25 static pid_t child;
26
27 static void checkchild(void)
28 {
29 int r, status;
30
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;
39
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 }
45 }
46
47 static HPState start(void)
48 {
49 assert(!child);
50
51 child= fork();
52 if (child == -1) {
53 Message(M_ERR,"hacky_par: fork failed: %s\n",strerror(errno));
54 return hp_fail;
55 }
56
57 if (!child) { /* we are the child */
58 return hp_compute;
59 }
60
61 Message(M_INFO,"hacky_par: started, punting\n");
62 return hp_deferring;
63 }
64
65 int hacky_par_start_failnow(void)
66 {
67 state= hp_idle;
68 checkchild();
69 if (child) {
70 state= hp_deferring;
71 Message(M_INFO,"hacky_par: busy, punting\n");
72 return 1;
73 }
74 return 0;
75 }
76
77 int hacky_par_mid_failnow(void)
78 {
79 state= start();
80 return state != hp_compute;
81 }
82
83 bool_t (*packy_par_gen)(struct site *st);
84
85 void hacky_par_end(int *ok,
86 int32_t retries, int32_t timeout,
87 bool_t (*send_msg)(struct site *st), struct site *st)
88 {
89 int i;
90
91 switch (state) {
92 case hp_deferring:
93 assert(!*ok);
94 *ok= 1;
95 return;
96 case hp_fail:
97 assert(!*ok);
98 return;
99 case hp_idle:
100 return;
101 case hp_compute:
102 if (!ok) {
103 Message(M_ERR,"hacky_par: compute failed\n");
104 _exit(2);
105 }
106 Message(M_INFO,"hacky_par: got result, sending\n");
107 for (i=1; i<retries; i++) {
108 sleep((timeout + 999)/1000);
109 if (!send_msg(st)) {
110 Message(M_ERR,"hacky_par: retry failed\n");
111 _exit(1);
112 }
113 }
114 _exit(0);
115 }
116 }
117
118 #else /*!HACKY_PARALLEL*/
119
120 int hacky_par_start_failnow(void) { return 0; }
121 int hacky_par_mid_failnow(void) { return 0; }
122 void hacky_par_end(int *ok,
123 int32_t retries, int32_t timeout,
124 bool_t (*send_msg)(struct site *st), struct site *st) { }
125
126 #endif /*HACKY_PARALLEL...else*/