예제 #1
0
파일: box.go 프로젝트: noxiouz/stout
// Spool spools code of an app from Cocaine Storage service
func (b *Box) Spool(ctx context.Context, name string, opts isolate.Profile) (err error) {
	spoolPath := b.spoolPath
	if val, ok := opts["spool"]; ok {
		spoolPath = fmt.Sprintf("%s", val)
	}
	defer apexctx.GetLogger(ctx).WithField("name", name).WithField("spoolpath", spoolPath).Trace("processBox.Spool").Stop(&err)
	data, err := b.fetch(ctx, name)
	if err != nil {
		return err
	}

	if isolate.IsCancelled(ctx) {
		return nil
	}

	return unpackArchive(ctx, data, filepath.Join(spoolPath, name))
}
예제 #2
0
파일: box.go 프로젝트: noxiouz/stout
// Spawn spawns a new process
func (b *Box) Spawn(ctx context.Context, config isolate.SpawnConfig, output io.Writer) (proc isolate.Process, err error) {
	spoolPath := b.spoolPath
	if val, ok := config.Opts["spool"]; ok {
		spoolPath = fmt.Sprintf("%s", val)
	}
	workDir := filepath.Join(spoolPath, config.Name)

	var execPath = config.Executable
	if !filepath.IsAbs(config.Executable) {
		execPath = filepath.Join(workDir, config.Executable)
	}

	packedEnv := make([]string, 0, len(config.Env))
	for k, v := range config.Env {
		packedEnv = append(packedEnv, k+"="+v)
	}

	packedArgs := make([]string, 1, len(config.Args)*2+1)
	packedArgs[0] = filepath.Base(config.Executable)
	for k, v := range config.Args {
		packedArgs = append(packedArgs, k, v)
	}

	defer apexctx.GetLogger(ctx).WithFields(
		log.Fields{"name": config.Name, "executable": config.Executable,
			"workDir": workDir, "execPath": execPath}).Trace("processBox.Spawn").Stop(&err)

	// Update statistics
	start := time.Now()
	spawningQueueSize.Inc(1)
	if spawningQueueSize.Count() > 10 {
		spawningQueueSize.Dec(1)
		return nil, syscall.EAGAIN
	}
	err = b.spawnSm.Acquire(ctx)
	spawningQueueSize.Dec(1)
	if err != nil {
		return nil, isolate.ErrSpawningCancelled
	}
	defer b.spawnSm.Release()
	// NOTE: once process was put to the map
	// its waiter responsibility to Wait for it.

	// NOTE: No defer here
	b.mu.Lock()
	if isolate.IsCancelled(ctx) {
		b.mu.Unlock()
		return nil, isolate.ErrSpawningCancelled
	}

	newProcStart := time.Now()
	pr, err := newProcess(ctx, execPath, packedArgs, packedEnv, workDir, output)
	newProcStarted := time.Now()
	// Update has lock, so move it out from Hot spot
	defer procsNewTimer.Update(newProcStarted.Sub(newProcStart))
	if err != nil {
		b.mu.Unlock()
		procsErroredCounter.Inc(1)
		return nil, err
	}
	b.children[pr.cmd.Process.Pid] = pr.cmd
	b.mu.Unlock()

	totalSpawnTimer.UpdateSince(start)
	isolate.NotifyAboutStart(output)
	procsCreatedCounter.Inc(1)
	return pr, err
}