3327759265843dc6651b46a2a54e69a72dfa9c98
[matches/swarm.git] / src / slave.c
1 #define _XOPEN_SOURCE
2 #define _GNU_SOURCE
3
4 //#define _SIMPLE_SLAVE
5
6 #include "slave.h"
7 #include <assert.h>
8
9 #include "network.h"
10 #include "daemon.h"
11 #include "log.h"
12 #include <errno.h>
13 #include <pty.h>
14 #include <fcntl.h>
15
16 #include <pthread.h>
17 #include <syslog.h>
18 #include <signal.h>
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <sys/wait.h>
22 #include <sys/socket.h>
23 #include <netinet/tcp.h>
24
25
26
27 Slave * slave;
28
29
30 int running;
31
32 void Slave_main(Options * o)
33 {
34         
35         if (fork() != 0)
36                 exit(EXIT_SUCCESS);
37
38
39         o->verbosity = 100;
40         freopen(SLAVE_LOGFILE, "w", stderr);
41         setbuf(stderr, NULL);
42         slave = (Slave*)(calloc(o->nCPU, sizeof(Slave)));
43
44         int net_fd = -1;
45         if (o->encrypt)
46                 net_fd = Network_client("localhost", o->port,100);
47         else
48                 net_fd = Network_client(o->master_addr, o->port,100);
49
50         FILE * f = fdopen(net_fd, "w"); setbuf(f, NULL);
51         fprintf(f, "%d\n", o->nCPU);
52
53         log_print(2, "Slave_main", "Waiting on bell from master");
54         char c;
55         if (read(net_fd, &c, sizeof(char)) == 0 || c != '\a')
56                 error("Slave_main", "Didn't get bell from master");
57         
58
59         
60
61         log_print(2, "Slave_main", "Got bell from master");
62         running = o->nCPU;
63         for (int i = 0; i < o->nCPU; ++i)
64         {
65                 int new_fd = net_fd;
66                 if (i != o->nCPU-1)
67                 {
68
69                         
70                         if (read(net_fd, &c, sizeof(char)) == 0 || c != '\a')
71                                 error("Slave_main", "Didn't get bell from master authorising connection of slave %d", i);
72                         sleep(1);
73
74                         log_print(3, "Slave_main", "Connecting slave %d to port %d at time %d", i, o->port+i+1, time(NULL));
75                         if (o->encrypt)
76                                 new_fd = Network_client("localhost", o->port+i+1, 100);
77                         else
78                                 new_fd = Network_client(o->master_addr, o->port+i+1, 100);
79
80                         
81                         
82                 }
83
84                 slave[i].in = new_fd; slave[i].out = new_fd;
85
86                 slave[i].pid = fork();
87                 if (slave[i].pid == 0)
88                 {
89                         dup2(slave[i].in, fileno(stdin));
90                         dup2(slave[i].out, fileno(stdout));
91                         execlp(o->shell, o->shell, NULL);
92                 }
93         }
94         
95         Slave_loop(o);
96
97         free(slave);
98         exit(EXIT_SUCCESS);
99 }
100
101 void Slave_loop(Options * o)
102 {
103         
104         int p = -1; int s = 0;
105         
106         while (running > 0)
107         {
108                 p = waitpid(-1, &s, 0);
109                 if (p == -1)
110                 {
111                         log_print(0, "Slave_loop", "waitpid : %s", strerror(errno));
112                         continue;
113                 }
114                 if (s != SHELL_EXIT_CODE)
115                 {
116                         // there was an error
117
118                         int i = 0;
119                         for (i = 0; i < o->nCPU; ++i)
120                         {
121                                 if (slave[i].pid == p) break;
122                         }
123                         if (i >= o->nCPU)
124                                 error("Slave_loop", "No child matches pid %d", p);
125
126                         log_print(0, "Slave_loop", "Child [%d] exits with status %d; restarting", p, s);
127                         slave[i].pid = fork();
128                         if (slave[i].pid == 0)
129                         {
130                                 dup2(slave[i].in, fileno(stdin));
131                                 dup2(slave[i].out, fileno(stdout));
132                                 execlp(o->shell, o->shell, NULL);
133                         }
134
135                         char buffer[] = "\f\a\a\a";
136                         if (write(slave[i].in, buffer, strlen(buffer)) <= 0)
137                                 log_print(0, "Slave_loop", "Slave %d input closed", i);
138                 }
139                 else
140                         --running;
141         }
142 }

UCC git Repository :: git.ucc.asn.au