Skip to content

Commit

Permalink
Fix the bugs about signal handler and closed conn
Browse files Browse the repository at this point in the history
This commit coplete the following tasks:

- Handle the SIGCONT and SIGSTOP with default signal handler. fix
  issue xcat2#3
- Receive the message from closed connection at first, then report
  EOF.
  • Loading branch information
chenglch committed Nov 13, 2017
1 parent c33eeb9 commit a3897ab
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 53 deletions.
8 changes: 5 additions & 3 deletions common/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ func (s *Network) ReceiveInt(conn net.Conn) (int, error) {
for n < 4 {
tmp, err := conn.Read(b[n:])
if err != nil {
if err == io.EOF && tmp+n == 4 {
return BytesToInt(b), err
}
return 0, err
}
n += tmp
Expand All @@ -58,9 +61,8 @@ func (s *Network) ReceiveIntTimeout(conn net.Conn, timeout time.Duration) (int,
}
tmp, err := conn.Read(b[n:])
if err != nil {
if err == io.EOF && tmp == n {
n += tmp
break
if err == io.EOF && tmp+n == 4 {
return BytesToInt(b), err
}
return 0, err
}
Expand Down
2 changes: 1 addition & 1 deletion common/signal.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func DoSignal() {
for sig := range s.GetSigMap() {
sigs = append(sigs, sig)
}
signal.Notify(c)
signal.Notify(c, sigs...)
sig := <-c
err := s.Handle(sig, nil)
if err != nil {
Expand Down
15 changes: 8 additions & 7 deletions console/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import (
"github.com/chenglch/goconserver/common"
"github.com/spf13/cobra"
"os"
"sort"
"strconv"
"strings"
"time"
"sort"
)

var (
Expand Down Expand Up @@ -58,6 +58,7 @@ type nodeHost struct {
host string
}
type nodeHostSlice []nodeHost

func (a nodeHostSlice) Len() int {
return len(a)
}
Expand Down Expand Up @@ -123,7 +124,7 @@ func (c *CongoCli) list(cmd *cobra.Command, args []string) {
tempNodes := make([]nodeHost, 0, len(nodes))
for _, v := range nodes {
node := v.(map[string]interface{})
tempNodes = append(tempNodes, nodeHost{name:node["name"].(string),
tempNodes = append(tempNodes, nodeHost{name: node["name"].(string),
host: node["host"].(string)})
}
sort.Sort(nodeHostSlice(tempNodes))
Expand All @@ -148,7 +149,7 @@ func (c *CongoCli) show(cmd *cobra.Command, args []string) {
fmt.Fprintf(os.Stderr, "Usage: congo show <node> \n")
os.Exit(1)
}
if strings.HasPrefix(".", args[0]) || strings.HasPrefix("/", args[0]){
if strings.HasPrefix(".", args[0]) || strings.HasPrefix("/", args[0]) {
fmt.Fprintf(os.Stderr, "Error: node name could not start with '.' or '/'\n")
os.Exit(1)
}
Expand Down Expand Up @@ -177,7 +178,7 @@ func (c *CongoCli) logging(cmd *cobra.Command, args []string) {
fmt.Fprintf(os.Stderr, "Usage: congo logging <node> on/off \n")
os.Exit(1)
}
if strings.HasPrefix(".", args[0]) || strings.HasPrefix("/", args[0]){
if strings.HasPrefix(".", args[0]) || strings.HasPrefix("/", args[0]) {
fmt.Fprintf(os.Stderr, "Error: node name could not start with '.' or '/'\n")
os.Exit(1)
}
Expand Down Expand Up @@ -208,7 +209,7 @@ func (c *CongoCli) delete(cmd *cobra.Command, args []string) {
fmt.Fprintf(os.Stderr, "Usage: congo delete <node>\n")
os.Exit(1)
}
if strings.HasPrefix(".", args[0]) || strings.HasPrefix("/", args[0]){
if strings.HasPrefix(".", args[0]) || strings.HasPrefix("/", args[0]) {
fmt.Fprintf(os.Stderr, "Error: node name could not start with '.' or '/'\n")
os.Exit(1)
}
Expand Down Expand Up @@ -239,7 +240,7 @@ func (c *CongoCli) create(cmd *cobra.Command, args []string) {
fmt.Fprintf(os.Stderr, "Usage: congo create <node> driver=ssh ondemand=true --param key=val,key=val\n")
os.Exit(1)
}
if strings.HasPrefix(".", args[0]) || strings.HasPrefix("/", args[0]){
if strings.HasPrefix(".", args[0]) || strings.HasPrefix("/", args[0]) {
fmt.Fprintf(os.Stderr, "Error: node name could not start with '.' or '/'\n")
os.Exit(1)
}
Expand Down Expand Up @@ -277,7 +278,7 @@ func (c *CongoCli) console(cmd *cobra.Command, args []string) {
fmt.Fprintf(os.Stderr, "Usage: congo console <node>\n")
os.Exit(1)
}
if strings.HasPrefix(".", args[0]) || strings.HasPrefix("/", args[0]){
if strings.HasPrefix(".", args[0]) || strings.HasPrefix("/", args[0]) {
fmt.Fprintf(os.Stderr, "Error: node name could not start with '.' or '/'\n")
os.Exit(1)
}
Expand Down
104 changes: 62 additions & 42 deletions console/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,76 +237,97 @@ func NewConsoleServer(host string, port string) *ConsoleServer {
return &ConsoleServer{host: host, port: port}
}

func (c *ConsoleServer) handle(conn interface{}) {
var err error
plog.Debug("New client connection received.")
func (c *ConsoleServer) getConnectionInfo(conn interface{}) (string, string) {
var node, command string
var ok bool
clientTimeout := time.Duration(serverConfig.Console.ClientTimeout)
size, err := c.ReceiveIntTimeout(conn.(net.Conn), clientTimeout)
if err != nil {
conn.(net.Conn).Close()
return
return "", ""
}
b, err := c.ReceiveBytesTimeout(conn.(net.Conn), size, clientTimeout)
if err != nil {
conn.(net.Conn).Close()
return
return "", ""
}
plog.Debug(fmt.Sprintf("Receive connection from client: %s", string(b)))
data := make(map[string]string)
if err := json.Unmarshal(b, &data); err != nil {
plog.Error(err)
err = c.SendIntWithTimeout(conn.(net.Conn), STATUS_ERROR, clientTimeout)
if err != nil {
plog.Error(err)
}
return "", ""
}
if node, ok = data["name"]; !ok {
plog.Error("Could not get the node from client")
return "", ""
}
if command, ok = data["command"]; !ok {
plog.Error("Could not get the command from client")
return "", ""
}
return node, command
}

func (c *ConsoleServer) redirect(conn interface{}, node string) {
var err error
nodeWithHost := nodeManager.stor.ListNodeWithHost()
clientTimeout := time.Duration(serverConfig.Console.ClientTimeout)
if _, ok := nodeWithHost[node]; !ok {
plog.ErrorNode(node, "Could not find this node.")
err = c.SendIntWithTimeout(conn.(net.Conn), STATUS_NOTFOUND, clientTimeout)
if err != nil {
plog.ErrorNode(node, err)
}
return
}
host := nodeWithHost[node]
err = c.SendIntWithTimeout(conn.(net.Conn), STATUS_REDIRECT, clientTimeout)
if err != nil {
plog.ErrorNode(node, err)
return
}
err = c.SendByteWithLength(conn.(net.Conn), []byte(host))
if err != nil {
plog.ErrorNode(node, err)
return
}
plog.InfoNode(node, fmt.Sprintf("Redirect the session to %s", host))
}

func (c *ConsoleServer) handle(conn interface{}) {
var err error
clientTimeout := time.Duration(serverConfig.Console.ClientTimeout)
plog.Debug("New client connection received.")
name, command := c.getConnectionInfo(conn)
if name == "" && command == "" {
conn.(net.Conn).Close()
return
}
plog.Debug(fmt.Sprintf("Receive connection from client: %s", string(b)))
if _, ok := nodeManager.Nodes[data["name"]]; !ok {
defer func() {
time.Sleep(time.Duration(1) * time.Second)
conn.(net.Conn).Close()
}()
if _, ok := nodeManager.Nodes[name]; !ok {
defer conn.(net.Conn).Close()
if !nodeManager.stor.SupportWatcher() {
plog.ErrorNode(data["name"], "Could not find this node.")
plog.ErrorNode(name, "Could not find this node.")
err = c.SendIntWithTimeout(conn.(net.Conn), STATUS_NOTFOUND, clientTimeout)
if err != nil {
plog.ErrorNode(data["name"], err)
plog.ErrorNode(name, err)
}
return
} else {
nodeWithHost := nodeManager.stor.ListNodeWithHost()
if _, ok := nodeWithHost[data["name"]]; !ok {
plog.ErrorNode(data["name"], "Could not find this node.")
err = c.SendIntWithTimeout(conn.(net.Conn), STATUS_NOTFOUND, clientTimeout)
if err != nil {
plog.ErrorNode(data["name"], err)
}
return
}
host := nodeWithHost[data["name"]]
err = c.SendIntWithTimeout(conn.(net.Conn), STATUS_REDIRECT, clientTimeout)
if err != nil {
plog.ErrorNode(data["name"], err)
return
}
err = c.SendByteWithLength(conn.(net.Conn), []byte(host))
if err != nil {
plog.ErrorNode(data["name"], err)
return
}
plog.InfoNode(data["name"], fmt.Sprintf("Redirect the session to %s", host))
c.redirect(conn, name)
}
return
}
node := nodeManager.Nodes[data["name"]]
if data["command"] == COMMAND_START_CONSOLE {
node := nodeManager.Nodes[name]
if command == COMMAND_START_CONSOLE {
if node.status != STATUS_CONNECTED {
if err = node.RequireLock(false); err != nil {
plog.ErrorNode(node.StorageNode.Name, fmt.Sprintf("Could not start console, error: %s.", err))
err = c.SendIntWithTimeout(conn.(net.Conn), STATUS_ERROR, clientTimeout)
if err != nil {
plog.ErrorNode(data["name"], err)
plog.ErrorNode(name, err)
}
conn.(net.Conn).Close()
return
Expand All @@ -320,7 +341,7 @@ func (c *ConsoleServer) handle(conn interface{}) {
node.Release(false)
err = c.SendIntWithTimeout(conn.(net.Conn), STATUS_ERROR, clientTimeout)
if err != nil {
plog.ErrorNode(data["name"], err)
plog.ErrorNode(name, err)
}
conn.(net.Conn).Close()
return
Expand All @@ -333,15 +354,15 @@ func (c *ConsoleServer) handle(conn interface{}) {
// reply success message to the client
err := c.SendIntWithTimeout(conn.(net.Conn), STATUS_CONNECTED, clientTimeout)
if err != nil {
plog.ErrorNode(data["name"], err)
plog.ErrorNode(name, err)
conn.(net.Conn).Close()
return
}
node.console.Accept(conn.(net.Conn))
} else {
err := c.SendIntWithTimeout(conn.(net.Conn), STATUS_ERROR, clientTimeout)
if err != nil {
plog.ErrorNode(data["name"], err)
plog.ErrorNode(name, err)
conn.(net.Conn).Close()
return
}
Expand Down Expand Up @@ -395,7 +416,6 @@ func (c *ConsoleServer) registerSignal() {
signalSet.Register(syscall.SIGINT, exitHandler)
signalSet.Register(syscall.SIGTERM, exitHandler)
signalSet.Register(syscall.SIGHUP, reloadHandler)
signalSet.Register(syscall.SIGCHLD, ignoreHandler)
signalSet.Register(syscall.SIGWINCH, ignoreHandler)
signalSet.Register(syscall.SIGPIPE, ignoreHandler)
go common.DoSignal()
Expand Down

0 comments on commit a3897ab

Please sign in to comment.