// waitForPayloadDeath blocks until the payload process stored at anchor exits, for whatever reason. // anchor is the anchor path used by the virus logic. func waitFotPayloadDeath(c *client.Client, payloadAnchor string) (recov interface{}) { // defer func() { // catch panics caused by unexpected death of the server hosting the payload // recov = recover() // }() t := c.Walk(client.Split(payloadAnchor)) // Access the process anchor of the currently-running payload of the virus. t.Get().(client.Proc).Wait() // Wait until the payload process exits. t.Scrub() // scrub payload anchor from old process element time.Sleep(2 * time.Second) // Wait a touch to slow down the spin return }
// waitForPayloadDeath blocks until the payload process stored at anchor exits, for whatever reason. // anchor is the anchor path used by the virus logic. func waitFotPayloadDeath(c *client.Client, myAnchor, payloadAnchor string, epoch int) (recov interface{}) { // catch panics caused by unexpected death of the server hosting the payload defer func() { recov = recover() }() // Access the process anchor of the currently-running payload of the virus. t := c.Walk(client.Split(payloadAnchor)) // Wait until the payload process exits. t.Get().(client.Proc).Wait() // Remove the anchor of the now-dead payload process. // t.Scrub() // Wait a touch to prevent spinning, if the payload exits immediately every time it is run. time.Sleep(time.Second / 2) return }
// Create or get back channel func findBackChan(c *client.Client, isNucleus bool) (backAnchor string, backChan client.Chan) { var err error if isNucleus { // The nucleus does not proceed with execution until it acquires permission // to send the the virus' back channel. backAnchor = os.Args[2] backChan = c.Walk(client.Split(backAnchor)).Get().(client.Chan) } else { // Make the back channel backServer := pickServer(c) backChan, err = backServer.Walk([]string{"virus", "back"}).MakeChan(3) if err != nil { println(err.Error()) os.Exit(1) } backAnchor = path.Join("/", backServer.ServerID(), "virus", "back") } return }
// The initial invocation of the virus: // virus DIALIN_CIRCUIT // To invoke the virus in the role of a nucleus process: // virus DIALIN_CIRCUIT PAYLOAD_ANCHOR SELF_ANCHOR // func main() { var payloadAnchor, nucleusAnchor string switch len(os.Args) { case 2: // initial command-line invocation case 4: // invocation in role of nucleus payloadAnchor = os.Args[2] nucleusAnchor = os.Args[3] default: println("usage: virus circuit://...") os.Exit(1) } println("virus dialing into", os.Args[1]) c := client.Dial(os.Args[1], nil) // The nucleus role waits for the payload process to die before it proceeds. if nucleusAnchor != "" { waitFotPayloadDeath(c, payloadAnchor) c.Walk(client.Split(nucleusAnchor)).Scrub() // remove anchor pointing to us } spawnNucleus(c, spawnPayload(c)) }
// waitForPayloadDeath blocks until the payload process stored at anchor exits, for whatever reason. // anchor is the anchor path used by the virus logic. func waitFotPayloadDeath(c *client.Client, anchor string) { // catch panics caused by unexpected death of the server hosting the payload defer func() { recover() }() // Access the process anchor that started this very process and // remove it to make room for the new one. // Note that scrubbing a process anchor removes the process element, // but in no way affects the underlying OS process. walkToVirus := client.Split(anchor) c.Walk(append(walkToVirus, "nucleus")).Scrub() // Access the process anchor of the currently-running payload of the virus. t := c.Walk(append(walkToVirus, "payload")) // Wait until the payload process exits. t.Get().(client.Proc).Wait() // Remove the anchor of the now-dead payload process. t.Scrub() // Wait a touch to prevent spinning, if the payload exits immediately every time it is run. time.Sleep(time.Second / 2) }