Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: node and webserver exit procedure #55

Merged
merged 4 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cli/runner.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020, The OTNS Authors.
// Copyright (c) 2020-2023, The OTNS Authors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -38,7 +38,7 @@ var (
)

func Run(cr *CmdRunner, cliOptions *runcli.CliOptions) error {
defer simplelogger.Debugf("CLI exit")
defer simplelogger.Debugf("CLI exit.")

return runcli.RunCli(cr, cliOptions)
}
Expand Down
7 changes: 5 additions & 2 deletions cmd/otns-replay/otns_replay.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022, The OTNS Authors.
// Copyright (c) 2022-2023, The OTNS Authors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -30,6 +30,7 @@ import (
"context"
"flag"
"net"
"net/http"
"os"

"github.com/openthread/ot-ns/progctx"
Expand Down Expand Up @@ -72,7 +73,9 @@ func main() {
go func() {
siteAddr := ":8997"
err := webSite.Serve(siteAddr)
simplelogger.PanicIfError(err)
if err != http.ErrServerClosed {
simplelogger.PanicIfError(err)
}
}()

go func() {
Expand Down
14 changes: 6 additions & 8 deletions dispatcher/dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ func (d *Dispatcher) Stop() {
d.GoCancel() // cancel current simulation period
d.vis.Stop()
close(d.pcapFrameChan)
simplelogger.Debugf("waiting for dispatcher threads exit ...")
simplelogger.Debugf("waiting for dispatcher threads to stop ...")
d.waitGroup.Wait()
simplelogger.Debugf("dispatcher exit.")
}
Expand Down Expand Up @@ -582,7 +582,8 @@ func (d *Dispatcher) processNextEvent(simSpeed float64) bool {

func (d *Dispatcher) eventsReader() {
defer d.waitGroup.Done()
defer os.RemoveAll(d.socketName) // delete socket file when done.
defer simplelogger.Debugf("dispatcher node socket threads stopped.")
defer os.RemoveAll(d.socketName) // delete Unix socket file when done.
defer d.udpln.Close()

simplelogger.Debugf("dispatcher listening on socket %s ...", d.socketName)
Expand Down Expand Up @@ -610,7 +611,7 @@ func (d *Dispatcher) eventsReader() {

buf := make([]byte, 65536)
myNodeId := 0
var myNode *Node = nil

for {
_ = myConn.SetReadDeadline(time.Now().Add(readTimeout))
n, err := myConn.Read(buf)
Expand All @@ -624,9 +625,6 @@ func (d *Dispatcher) eventsReader() {
continue
} else if err != nil {
simplelogger.Errorf("Node %d - Socket read error: %+v", myNodeId, err)
if myNode != nil && myNode.err == nil {
myNode.err = err
}
break
}

Expand All @@ -648,8 +646,8 @@ func (d *Dispatcher) eventsReader() {
}(conn)
}

simplelogger.Debugf("dispatcher waiting for node socket threads to exit ...")
d.waitGroupNodes.Wait() // wait for all nodes to exit before closing eventsReader.
simplelogger.Debugf("waiting for dispatcher node socket threads to stop ...")
d.waitGroupNodes.Wait() // wait for all node goroutines to stop before closing eventsReader.
}

func (d *Dispatcher) advanceNodeTime(node *Node, timestamp uint64, force bool) {
Expand Down
10 changes: 5 additions & 5 deletions otns_main/otns_main.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,15 @@ func Main(ctx *progctx.ProgCtx, visualizerCreator func(ctx *progctx.ProgCtx, arg
vis = visualizeGrpc.NewGrpcVisualizer(visGrpcServerAddr, replayFn)
}

ctx.WaitAdd("webserver", 1)
go func() {
defer ctx.WaitDone("webserver")
siteAddr := fmt.Sprintf("%s:%d", args.DispatcherHost, args.DispatcherPort-3)
err := webSite.Serve(siteAddr) // blocks until webSite.StopServe() called
if err != nil && ctx.Err() == nil {
simplelogger.Errorf("website stopped unexpectedly: %+v, OTNS-Web won't be available!", err)
} else if err != nil {
simplelogger.Debugf("website stopped while exiting: %+v", err)
simplelogger.Errorf("webserver stopped unexpectedly: %+v, OTNS-Web won't be available!", err)
}
}()
defer webSite.StopServe()

sim := createSimulation(ctx)
rt := cli.NewCmdRunner(ctx, sim)
Expand All @@ -202,6 +201,7 @@ func Main(ctx *progctx.ProgCtx, visualizerCreator func(ctx *progctx.ProgCtx, arg
vis.Run() // visualize must run in the main thread

simplelogger.Debugf("waiting for OTNS to stop gracefully ...")
webSite.StopServe()
ctx.Wait()
}

Expand All @@ -212,8 +212,8 @@ func handleSignals(ctx *progctx.ProgCtx) {

ctx.WaitAdd("handleSignals", 1)
go func() {
defer simplelogger.Debugf("handleSignals exit.")
defer ctx.WaitDone("handleSignals")
defer simplelogger.Debugf("waiting for handleSignals exit.")

for {
select {
Expand Down
2 changes: 1 addition & 1 deletion otnstester/OtnsTest.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ func NewOtnsTest(t *testing.T) *OtnsTest {

go func() {
defer func() {
simplelogger.Infof("OTNS exited.")
simplelogger.Infof("OTNS exit.")
close(ot.otnsDone)
}()

Expand Down
4 changes: 2 additions & 2 deletions progctx/progctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ func (ctx *ProgCtx) Cancel(err interface{}) {
ctx.cancel()

if e, ok := err.(error); ok {
simplelogger.TraceError("program exit: %v", e)
simplelogger.TraceError("program exit requested with ctx error: %v", e)
} else {
simplelogger.Infof("program exit: %v", err)
simplelogger.Debugf("program exit requested without ctx error: %v", err)
}

for _, f := range ctx.deferred {
Expand Down
5 changes: 3 additions & 2 deletions pylibs/stress_tests/network_forming.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@

XGAP = 100
YGAP = 100
RADIO_RANGE = int(XGAP * 1.5)
RADIO_RANGE = int(XGAP * 1.8)

MIN_N = 1
MAX_N = 6

REPEAT = int(os.getenv('STRESS_LEVEL', '1')) * 3
REPEAT = 6

EXPECTED_MERGE_TIME_MAX = [
None, 10, 14, 40, 60, 130, 190
Expand All @@ -66,6 +66,7 @@ def __init__(self):

def run(self):
# self.ns.config_visualization(broadcast_message=False)
self.ns.radiomodel = 'MutualInterference'

for n in range(MIN_N, MAX_N + 1):
durations = []
Expand Down
4 changes: 2 additions & 2 deletions pylibs/unittests/test_signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ def testSIGINT(self):
def testSIGTERM(self):
self._test_signal_exit(signal.SIGTERM)

def testSIGTERMx500(self):
N = 500
def testSIGTERMx200(self):
N = 200
for i in range(N):
logging.info("round %d", i + 1)
self._test_signal_exit(signal.SIGTERM, 0.1 * random.random())
Expand Down
14 changes: 9 additions & 5 deletions simulation/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,18 +179,19 @@ func (node *Node) Stop() {
simplelogger.Debugf("%v - stopped, state = %s", node, node.GetState())
}

func (node *Node) SignalExit() error {
return node.cmd.Process.Signal(syscall.SIGTERM)
}

func (node *Node) Exit() error {
_ = node.cmd.Process.Signal(syscall.SIGTERM)

node.S.Dispatcher().RecvEvents() // ensure to receive any remaining events of node.

// no more events or lineReader lines should come, so we can close the virtual-UART.
// no more events or lineReader lines will be accepted, so we close the virtual-UART.
// pipes are closed to allow cmd.Wait() to be successful and not hang.
_ = node.pipeIn.Close()
_ = node.pipeErr.Close()
_ = node.pipeOut.Close()
_ = node.virtualUartReader.Close()

err := node.cmd.Wait() // wait for process end

if node.logFile != nil {
Expand Down Expand Up @@ -838,7 +839,10 @@ func (node *Node) writeToLogFile(line string) {

_, err := node.logFile.WriteString(fmt.Sprintf("%-10d ", timestamp) + line + "\n")
if err != nil {
simplelogger.Error("Couldn't write to log file of %v, closing it (%s)", node, node.logFile)
if node.S.ctx.Err() == nil {
simplelogger.Debugf("ctx.Err()=%v", node.S.ctx.Err())
simplelogger.Errorf("Couldn't write to log file of %v, closing it (%s)", node, node.logFile.Name())
}
_ = node.logFile.Close()
node.logFile = nil
}
Expand Down
2 changes: 1 addition & 1 deletion simulation/node_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func NewNodeAutoPlacer() *NodeAutoPlacer {
return &NodeAutoPlacer{
Xref: 100,
Yref: 100,
Xmax: 1500,
Xmax: 1450,
X: 100,
Y: 100,
NodeDeltaCoarse: 100,
Expand Down
11 changes: 11 additions & 0 deletions simulation/simulation.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,18 @@ func (s *Simulation) Stop() {
simplelogger.Infof("stopping simulation and exiting nodes ...")
s.stopped = true

// for faster process, signal node exit first in parallel.
for _, node := range s.nodes {
_ = node.SignalExit()
}
s.Dispatcher().RecvEvents() // meanwhile receive any events of (exiting) nodes.

// then clean up and wait for each node process to stop, sequentially.
for _, node := range s.nodes {
_ = node.Exit()
}
s.Dispatcher().RecvEvents() // ensure to receive any remaining events of exited nodes.

simplelogger.Debugf("all simulation nodes exited.")
}

Expand Down Expand Up @@ -288,6 +297,7 @@ func (s *Simulation) MoveNodeTo(nodeid NodeId, x, y int) {
return
}
s.d.SetNodePos(nodeid, x, y)
s.nodePlacer.UpdateReference(x, y)
}

func (s *Simulation) DeleteNode(nodeid NodeId) error {
Expand All @@ -299,6 +309,7 @@ func (s *Simulation) DeleteNode(nodeid NodeId) error {

delete(s.nodes, nodeid)
_ = node.Exit()
s.d.RecvEvents() // ensure to receive any final events of deleted node.
s.d.DeleteNode(nodeid)
return nil
}
Expand Down
11 changes: 4 additions & 7 deletions visualize/grpc/grpcVisualizer.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020-2022, The OTNS Authors.
// Copyright (c) 2020-2023, The OTNS Authors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -32,14 +32,11 @@ import (
"time"

"github.com/openthread/ot-ns/energy"
"github.com/openthread/ot-ns/visualize/grpc/replay"

"github.com/simonlingoogle/go-simplelogger"

pb "github.com/openthread/ot-ns/visualize/grpc/pb"

. "github.com/openthread/ot-ns/types"
"github.com/openthread/ot-ns/visualize"
pb "github.com/openthread/ot-ns/visualize/grpc/pb"
"github.com/openthread/ot-ns/visualize/grpc/replay"
"github.com/simonlingoogle/go-simplelogger"
)

type grpcVisualizer struct {
Expand Down
2 changes: 1 addition & 1 deletion web/site/bindata.go

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions web/site/js/vis/ActionBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,6 @@ export default class ActionBar extends VObject {
}

onDraggingDone() {
// just above the ActionBar's new position is where new nodes will be auto-placed.
this.vis.ctrlSetNewNodePosition(this.position.x, this.position.y - NODE_SPACING_ABOVE_ACTIONBAR_PX);
//
}
}
15 changes: 9 additions & 6 deletions web/site/js/vis/LogWindow.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020, The OTNS Authors.
// Copyright (c) 2020-2023, The OTNS Authors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -27,13 +27,16 @@
import * as PIXI from "pixi.js-legacy";
import VObject from "./VObject";
import {Scrollbox} from 'pixi-scrollbox'
import {
LOG_WINDOW_FONT_FAMILY, LOG_WINDOW_FONT_SIZE, LOG_WINDOW_FONT_COLOR
} from "./consts";


const LOG_TEXT_STYLE = {
fill: "#0052ff",
fontFamily: "Verdana",
fontSize: 11,
fontStyle: "italic",
fill: LOG_WINDOW_FONT_COLOR,
fontFamily: LOG_WINDOW_FONT_FAMILY,
fontSize: LOG_WINDOW_FONT_SIZE,
fontStyle: "normal",
fontWeight: "normal"
};

Expand Down Expand Up @@ -70,7 +73,7 @@ export default class LogWindow extends VObject {
this.loglist = [];
}

addLog(text, color = "#0052ff") {
addLog(text, color = LOG_WINDOW_FONT_COLOR) {
if (this.loglist.length === LOG_WINDOW_MAX_SIZE) {
let rm = this.loglist.shift();
this.logContainer.removeChild(rm)
Expand Down
15 changes: 7 additions & 8 deletions web/site/js/vis/PixiVisualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ import * as PIXI from "pixi.js-legacy";
import VObject from "./VObject";
import ActionBar from "./ActionBar";
import {Text} from "./wrapper";
import {FRAME_CONTROL_MASK_FRAME_TYPE, FRAME_TYPE_ACK, MAX_SPEED, PAUSE_SPEED, NODE_AUTOSPACING_PX,
NODE_AUTOSPACING_FINE_PX} from "./consts";
import {
FRAME_CONTROL_MASK_FRAME_TYPE, FRAME_TYPE_ACK, LOG_WINDOW_FONT_COLOR, MAX_SPEED, PAUSE_SPEED
} from "./consts";
import Node from "./Node"
import {AckMessage, BroadcastMessage, UnicastMessage} from "./message";
import LogWindow, {LOG_WINDOW_WIDTH} from "./LogWindow";
Expand Down Expand Up @@ -258,7 +259,7 @@ export default class PixiVisualizer extends VObject {
return count
}

log(text, color = '#0052ff') {
log(text, color = LOG_WINDOW_FONT_COLOR) {
if (this.logWindow) {
this.logWindow.addLog(text, color)
}
Expand Down Expand Up @@ -470,6 +471,7 @@ export default class PixiVisualizer extends VObject {
}
}

// Set the position (x,y) for the next new node to be placed.
ctrlSetNewNodePosition(x, y) {
x = Math.round(x);
y = Math.round(y);
Expand Down Expand Up @@ -679,11 +681,8 @@ export default class PixiVisualizer extends VObject {
}

randomColor() {
const letters = '0123456789ABCDEF';
let color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
let hue = Math.floor(Math.random() * 360);
let color = `hsl(${hue}deg, 92%, 23%)`;
return color;
}

Expand Down
6 changes: 3 additions & 3 deletions web/site/js/vis/consts.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ export const FRAME_TYPE_ACK = 2;
export const COLOR_ACK_MESSAGE = 0xaee571;
export const BUTTON_LABEL_FONT_FAMILY = 'verdana, helvetica, sans-serif';
export const NODE_LABEL_FONT_FAMILY = 'helvetica, arial, monospace, sans-serif';

// size constants
export const NODE_SPACING_ABOVE_ACTIONBAR_PX = 80;
export const LOG_WINDOW_FONT_FAMILY = 'verdana, helvetica, sans-serif';
export const LOG_WINDOW_FONT_SIZE = 11.5
export const LOG_WINDOW_FONT_COLOR = "Blue"
Loading
Loading