code: func (a *customAdapter) shutdownWorkerProcess(ctx *customAdapterWorkerContext) error {
  	defer ctx.errTracer.Flush()
  
  	a.Trace("xfer: Shutting down adapter worker %d", ctx.workerNum)
  
  	finishChan := make(chan error, 1)
  	go func() {
  		termReq := NewCustomAdapterTerminateRequest()
  		err := a.sendMessage(ctx, termReq)
  		if err != nil {
  			finishChan <- err
  		}
  		ctx.stdin.Close()
  		ctx.stdout.Close()
  		finishChan <- ctx.cmd.Wait()
  	}()
  	select {
  	case err := <-finishChan:
  		return err
  	case <-time.After(30 * time.Second):
  		return fmt.Errorf("Timeout while shutting down worker process %d", ctx.workerNum)
  	}
  }
docs: // shutdownWorkerProcess terminates gracefully a custom adapter process
  // returns an error if it couldn't shut down gracefully (caller may abortWorkerProcess)