예제 #1
0
func ctx() *Ctx {
	c := AppCtx()
	if c == nil {
		dbg.Fatal("no context for %d", runtime.AppId())
	}
	return c
}
예제 #2
0
// Return the current app context.
func AppCtx() *Ctx {
	ctxlk.Lock()
	defer ctxlk.Unlock()
	id := runtime.AppId()
	c := ctxs[id]
	if c == nil {
		return nil
	}
	return c
}
예제 #3
0
// Create a new application context, it's methods are
// implicit and accessed using the runtime application context.
// It's a panic to call New twice in the same process.
// IO, Env, Dot, and Ns are shared with the parent context by default.
// Use NewX() or DupX(), to start using new ones or create dups.
// The first context created initializes them from the underlying OS.
func New() *Ctx {
	usingApp = true
	old := runtime.AppId()
	ctxlk.Lock()
	pc := ctxs[old]
	n := len(ctxs)
	ctxlk.Unlock()
	runtime.NewApp()
	id := runtime.AppId()
	if old == id && n > 0 {
		panic("runtime bug: old ctx == new ctx")
	}
	c := mkCtx(id)
	ctxlk.Lock()
	if ctxs[id] != nil {
		panic("app.new: double call")
	}
	ctxs[id] = c
	ctxlk.Unlock()
	dprintf("new ctx %d\n", c.Id)
	if n == 0 {
		c.Args = os.Args
	}
	if pc != nil {
		pc.io.lk.Lock()
		pc.io.n++
		pc.io.lk.Unlock()
		pc.lk.Lock()
		c.env = pc.env
		c.dot = pc.dot
		c.ns = pc.ns
		c.io = pc.io
		c.bg = pc.bg
		pc.lk.Unlock()
	} else {
		NewEnv(nil)
		NewDot("")
		NewNS(nil)
		NewIO(nil)
	}
	dump("new")
	return c
}
예제 #4
0
func fatal(warn bool, args ...interface{}) {

	c := AppCtx()
	dprintf("fatal...\n")
	dump("fatal")
	if c == nil {
		panic("fatal")
	}
	ctxlk.Lock() 
	n := len(ctxs)
	ctxlk.Unlock()
	sts := mkSts(args...)
	efn := func() {
		c.post("exit")
		c.Sts = sts
		c.io.closeAll(sts)
		close(c.Sig, sts)
		close(c.Wait, sts)
		ctxlk.Lock()
		delete(ctxs, runtime.AppId())
		ctxlk.Unlock()
	}
	if n <= 1 {
		dprintf("c %d: dbg fatal (%d args)\n", c.Id, len(args))
		efn()
		close(out)
		close(err)
		<-outdone
		<-errdone
		os.Args = c.Args
		if warn {
			dbg.Fatal(args...)	// never returns
		} else {
			dbg.Exits(args...)	// never returns
		}
	}
	dprintf("c %d: app fatal (%d args, %d apps)\n", c.Id, len(args), n)
	if sts != nil && warn {
		Warn("%s", sts)
	}
	efn()
	panic("fatal")
}
예제 #5
0
// To be deferred in the main program so it recovers from Fatals and returns.
// For safety, Atexits are run by the call to Fatal and not here.
func Exiting() {
	if r := recover(); r != nil {
		dprintf("exiting: %v...\n", r)
		if r == "fatal" {
			return
		}
		panic(r)
	}
	dprintf("exiting...\n")
	dump("exiting")
	ctxlk.Lock()
	id := runtime.AppId()
	c := ctxs[id]
	delete(ctxs, id)
	ctxlk.Unlock()
	if c != nil && c.io != nil {
		c.io.closeAll(nil)
	}
}
예제 #6
0
func vprintf(fmts string, args ...interface{}) {
	if !Debug || !Verb {
		return
	}
	dbg.Printf("%d: %s", runtime.AppId(), fmt.Sprintf(fmts, args...))
}
예제 #7
0
// returns true if the app ctx exited
func Exited() bool {
	ctxlk.Lock()
	defer ctxlk.Unlock()
	return ctxs[runtime.AppId()] == nil
}