Introducing Unit version check in Go package.
To communicate with the Go program, Unit setup environment variable named NXT_GO_PORTS with value contains Unit version, stream id to confirm application is started, and Unit ports information. Go Unit package parses this string and compares runtime version with compile time version. In case of parse error or version mismatch, ListenAndServe() returns with the error.
This commit is contained in:
@@ -112,18 +112,11 @@ nxt_go_request_done(nxt_go_request_t r)
|
||||
|
||||
|
||||
void
|
||||
nxt_go_ready()
|
||||
nxt_go_ready(uint32_t stream)
|
||||
{
|
||||
char *go_stream;
|
||||
nxt_port_msg_t port_msg;
|
||||
nxt_port_msg_t port_msg;
|
||||
|
||||
go_stream = getenv("NXT_GO_STREAM");
|
||||
|
||||
if (go_stream == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
port_msg.stream = atol(go_stream);
|
||||
port_msg.stream = stream;
|
||||
port_msg.pid = getpid();
|
||||
port_msg.reply_port = 0;
|
||||
port_msg.type = _NXT_PORT_MSG_PROCESS_READY;
|
||||
@@ -141,3 +134,10 @@ nxt_go_process_port_msg(uintptr_t buf, size_t buf_len, uintptr_t oob, size_t oob
|
||||
{
|
||||
return nxt_go_port_on_read((void *) buf, buf_len, (void *) oob, oob_len);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
nxt_go_version()
|
||||
{
|
||||
return NXT_VERSION;
|
||||
}
|
||||
|
||||
@@ -30,10 +30,12 @@ int nxt_go_request_close(nxt_go_request_t r);
|
||||
|
||||
int nxt_go_request_done(nxt_go_request_t r);
|
||||
|
||||
void nxt_go_ready();
|
||||
void nxt_go_ready(uint32_t stream);
|
||||
|
||||
nxt_go_request_t nxt_go_process_port_msg(uintptr_t buf, size_t buf_len,
|
||||
uintptr_t oob, size_t oob_len);
|
||||
|
||||
const char *nxt_go_version();
|
||||
|
||||
|
||||
#endif /* _NXT_GO_LIB_H_INCLUDED_ */
|
||||
|
||||
@@ -11,6 +11,7 @@ package unit
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -65,31 +66,53 @@ func ListenAndServe(addr string, handler http.Handler) error {
|
||||
var read_port *port
|
||||
|
||||
go_ports_env := os.Getenv("NXT_GO_PORTS")
|
||||
if go_ports_env == "" {
|
||||
return http.ListenAndServe(addr, handler)
|
||||
}
|
||||
|
||||
nxt_go_debug("NXT_GO_PORTS=%s", go_ports_env)
|
||||
|
||||
ports := strings.Split(go_ports_env, ";")
|
||||
pid := os.Getpid()
|
||||
|
||||
for _, port_str := range ports {
|
||||
if len(port_str) <= 0 {
|
||||
continue
|
||||
}
|
||||
if len(ports) != 4 {
|
||||
return errors.New("Invalid NXT_GO_PORTS format")
|
||||
}
|
||||
|
||||
nxt_go_debug("version=%s", ports[0])
|
||||
|
||||
builtin_version := C.GoString(C.nxt_go_version())
|
||||
|
||||
if ports[0] != builtin_version {
|
||||
return fmt.Errorf("Versions mismatch: Unit %s, while application is built with %s",
|
||||
ports[0], builtin_version)
|
||||
}
|
||||
|
||||
stream, stream_err := strconv.Atoi(ports[1])
|
||||
if stream_err != nil {
|
||||
return stream_err
|
||||
}
|
||||
|
||||
read_port = nil
|
||||
|
||||
for _, port_str := range ports[2:] {
|
||||
attrs := strings.Split(port_str, ",")
|
||||
|
||||
if len(attrs) != 5 {
|
||||
return fmt.Errorf("Invalid port format: unexpected port attributes number %d, while 5 expected",
|
||||
len(attrs))
|
||||
}
|
||||
|
||||
var attrsN [5]int
|
||||
var err error
|
||||
for i, attr := range attrs {
|
||||
attrsN[i], err = strconv.Atoi(attr)
|
||||
if err != nil {
|
||||
fmt.Printf("err %s\n", err)
|
||||
break
|
||||
return fmt.Errorf("Invalid port format: number attribute expected at %d position instead of '%s'",
|
||||
i, attr);
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
p := new_port(attrsN[0], attrsN[1], attrsN[2], attrsN[3], attrsN[4])
|
||||
|
||||
if attrsN[0] == pid {
|
||||
@@ -97,17 +120,17 @@ func ListenAndServe(addr string, handler http.Handler) error {
|
||||
}
|
||||
}
|
||||
|
||||
if read_port != nil {
|
||||
C.nxt_go_ready()
|
||||
if read_port == nil {
|
||||
return errors.New("Application read port not found");
|
||||
}
|
||||
|
||||
for !nxt_go_quit {
|
||||
err := read_port.read(handler)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
C.nxt_go_ready(C.uint32_t(stream))
|
||||
|
||||
for !nxt_go_quit {
|
||||
err := read_port.read(handler)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return http.ListenAndServe(addr, handler)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user