-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcloci.go
136 lines (102 loc) · 3.42 KB
/
cloci.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package main
import (
"context"
"os"
"os/signal"
"syscall"
"codelearning.online/conf"
"codelearning.online/https_server"
"codelearning.online/logger"
)
var (
service_waiter_channel chan bool
https_server_handle *https_server.Handle
version string
)
// Signal handlers
func sigint_handler() {
// TO-DO: call clean_up(), delete the following
logger.Debug("SIGINT received")
// Stops the service.
service_waiter_channel <- true
}
func sigterm_handler() {
// TO-DO: call clean_up(), delete the following
logger.Debug("SIGTERM received")
// Stops the service.
service_waiter_channel <- true
}
func sigkill_handler() {
// TO-DO: call clean_up(), delete the following
logger.Debug("SIGKILL received")
// Stops the service.
service_waiter_channel <- true
}
func set_signal_handlers(sigint_handler func(), sigterm_handler func(), sigkill_handler func()) {
// Initializes a channel for OS signals.
signals_channel := make(chan os.Signal, 1)
// Ignores all incoming signals.
signal.Ignore()
// We will process SIGINTs, SIGTERMs, SIGKILLs, and SIGCHLD only.
// SIGKILL will not be caught on FreeBSD. See https://pkg.go.dev/os/signal
// SIGCHLD is needed to correctly perform wait(6) syscalls.
signal.Notify(signals_channel, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL, syscall.SIGCHLD)
// Starts a signal processing routine.
// It reacts the same on the both signals.
go func() {
for received_signal := range signals_channel {
logger.Debug("%v received", received_signal)
switch received_signal {
case syscall.SIGINT:
sigint_handler()
case syscall.SIGTERM:
sigterm_handler()
case syscall.SIGKILL:
sigkill_handler()
}
}
}()
logger.Info("Signal handlers were set up")
}
func init() {
// Checks whether logger works or not.
// If not, stops the service.
if err := logger.Check(); err != nil {
os.Exit(int(err.(*logger.ClpError).Code))
}
// Show current version of the service.
// To change it, compile with
// go build -ldflags "-X main.version=<major.minor.patch>"
logger.Info("\nCodeLearning Online Compiler-Interpreter v.%s\nCopyright Mark Laptenok, 2021-2022", version)
// Sets handlers for SIGINT, SIGTERM, and SIGKILL signals.
// Note: SIGKILL is not processed on FreeBSD.
service_waiter_channel = make(chan bool, 1)
set_signal_handlers(sigint_handler, sigterm_handler, sigkill_handler)
// Reads service configuration from the command line arguments first
// and from the conf file the second.
// If reading fails, so we don't have a proper configuration, stops the service.
var cnf *conf.ClociConfiguration
var err error
if cnf, err = conf.Read(os.Args[1:]); err != nil {
logger.Error(err)
}
// If we are here, than logger works and necessary OS process signals are ready for being processed,
// and a configuration ('cnf') is set.
// Allocates the processors which one by one will process clients' requests.
processors := make([]func(ctx context.Context, message []byte) (context.Context, []byte, error), 3)
processors[0] = parse_request
processors[1] = build_and_run_code
processors[2] = encode_response
// Starts serving of incoming requests.
// In case of error, stops the service.
if https_server_handle, err = https_server.Start(cnf, processors); err != nil {
logger.Error(err)
}
}
func main() {
<-service_waiter_channel
if https_server_handle != nil {
https_server_handle.Stop()
}
logger.Info("Service is gracefully stopped. Have a good day!")
}