<commit_before>package rt_test

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/signal"
	"sync"
	"syscall"

	"veyron.io/veyron/veyron2/ipc"
	"veyron.io/veyron/veyron2/rt"
	"veyron.io/veyron/veyron2/vlog"

	"veyron.io/veyron/veyron/lib/modules"
	"veyron.io/veyron/veyron/lib/signals"
	"veyron.io/veyron/veyron/profiles"
)

func init() {
	modules.RegisterChild("simpleServerProgram", "", simpleServerProgram)
	modules.RegisterChild("complexServerProgram", "", complexServerProgram)
}

type dummy struct{}

func (*dummy) Echo(ipc.ServerContext) error { return nil }

// makeServer sets up a simple dummy server.
func makeServer() ipc.Server {
	server, err := rt.R().NewServer()
	if err != nil {
		vlog.Fatalf("r.NewServer error: %s", err)
	}
	if _, err := server.Listen(profiles.LocalListenSpec); err != nil {
		vlog.Fatalf("server.Listen error: %s", err)
	}
	if err := server.Serve("", &dummy{}, nil); err != nil {
		vlog.Fatalf("server.Serve error: %s", err)
	}
	return server
}

// remoteCmdLoop listens on stdin and interprets commands sent over stdin (from
// the parent process).
func remoteCmdLoop(stdin io.Reader) func() {
	done := make(chan struct{})
	go func() {
		defer close(done)
		scanner := bufio.NewScanner(stdin)
		for scanner.Scan() {
			switch scanner.Text() {
			case "stop":
				rt.R().AppCycle().Stop()
			case "forcestop":
				fmt.Println("straight exit")
				rt.R().AppCycle().ForceStop()
			case "close":
				return
			}
		}
	}()
	return func() { <-done }
}

// complexServerProgram demonstrates the recommended way to write a more
// complex server application (with several servers, a mix of interruptible
// and blocking cleanup, and parallel and sequential cleanup execution).
// For a more typical server, see simpleServerProgram.
func complexServerProgram(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
	// Initialize the runtime.  This is boilerplate.
	r := rt.Init()

	// This is part of the test setup -- we need a way to accept
	// commands from the parent process to simulate Stop and
	// RemoteStop commands that would normally be issued from
	// application code.
	defer remoteCmdLoop(stdin)()

	// r.Cleanup is optional, but it's a good idea to clean up, especially
	// since it takes care of flushing the logs before exiting.
	defer r.Cleanup()

	// Create a couple servers, and start serving.
	server1 := makeServer()
	server2 := makeServer()

	// This is how to wait for a shutdown.  In this example, a shutdown
	// comes from a signal or a stop command.
	var done sync.WaitGroup
	done.Add(1)

	// This is how to configure signal handling to allow clean shutdown.
	sigChan := make(chan os.Signal, 2)
	signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)

	// This is how to configure handling of stop commands to allow clean
	// shutdown.
	stopChan := make(chan string, 2)
	r.AppCycle().WaitForStop(stopChan)

	// Blocking is used to prevent the process from exiting upon receiving a
	// second signal or stop command while critical cleanup code is
	// executing.
	var blocking sync.WaitGroup
	blockingCh := make(chan struct{})

	// This is how to wait for a signal or stop command and initiate the
	// clean shutdown steps.
	go func() {
		// First signal received.
		select {
		case sig := <-sigChan:
			// If the developer wants to take different actions
			// depending on the type of signal, they can do it here.
			fmt.Fprintln(stdout, "Received signal", sig)
		case stop := <-stopChan:
			fmt.Fprintln(stdout, "Stop", stop)
		}
		// This commences the cleanup stage.
		done.Done()
		// Wait for a second signal or stop command, and force an exit,
		// but only once all blocking cleanup code (if any) has
		// completed.
		select {
		case <-sigChan:
		case <-stopChan:
		}
		<-blockingCh
		os.Exit(1)
	}()

	// This communicates to the parent test driver process in our unit test
	// that this server is ready and waiting on signals or stop commands.
	// It's purely an artifact of our test setup.
	fmt.Fprintln(stdout, "Ready")

	// Wait for shutdown.
	done.Wait()

	// Stop the servers.  In this example we stop them in goroutines to
	// parallelize the wait, but if there was a dependency between the
	// servers, the developer can simply stop them sequentially.
	var waitServerStop sync.WaitGroup
	waitServerStop.Add(2)
	go func() {
		server1.Stop()
		waitServerStop.Done()
	}()
	go func() {
		server2.Stop()
		waitServerStop.Done()
	}()
	waitServerStop.Wait()
<commit_msg>veyron/runtime/google: fix potential race in shutdown_test<commit_after>package rt_test

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/signal"
	"sync"
	"syscall"

	"veyron.io/veyron/veyron2/ipc"
	"veyron.io/veyron/veyron2/rt"
	"veyron.io/veyron/veyron2/vlog"

	"veyron.io/veyron/veyron/lib/modules"
	"veyron.io/veyron/veyron/lib/signals"
	"veyron.io/veyron/veyron/profiles"
)

func init() {
	modules.RegisterChild("simpleServerProgram", "", simpleServerProgram)
	modules.RegisterChild("complexServerProgram", "", complexServerProgram)
}

type dummy struct{}

func (*dummy) Echo(ipc.ServerContext) error { return nil }

// makeServer sets up a simple dummy server.
func makeServer() ipc.Server {
	server, err := rt.R().NewServer()
	if err != nil {
		vlog.Fatalf("r.NewServer error: %s", err)
	}
	if _, err := server.Listen(profiles.LocalListenSpec); err != nil {
		vlog.Fatalf("server.Listen error: %s", err)
	}
	if err := server.Serve("", &dummy{}, nil); err != nil {
		vlog.Fatalf("server.Serve error: %s", err)
	}
	return server
}

// remoteCmdLoop listens on stdin and interprets commands sent over stdin (from
// the parent process).
func remoteCmdLoop(stdin io.Reader) func() {
	done := make(chan struct{})
	go func() {
		scanner := bufio.NewScanner(stdin)
		for scanner.Scan() {
			switch scanner.Text() {
			case "stop":
				rt.R().AppCycle().Stop()
			case "forcestop":
				fmt.Println("straight exit")
				rt.R().AppCycle().ForceStop()
			case "close":
				close(done)
				return
			}
		}
	}()
	return func() { <-done }
}

// complexServerProgram demonstrates the recommended way to write a more
// complex server application (with several servers, a mix of interruptible
// and blocking cleanup, and parallel and sequential cleanup execution).
// For a more typical server, see simpleServerProgram.
func complexServerProgram(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
	// Initialize the runtime.  This is boilerplate.
	r := rt.Init()

	// This is part of the test setup -- we need a way to accept
	// commands from the parent process to simulate Stop and
	// RemoteStop commands that would normally be issued from
	// application code.
	defer remoteCmdLoop(stdin)()

	// r.Cleanup is optional, but it's a good idea to clean up, especially
	// since it takes care of flushing the logs before exiting.
	defer r.Cleanup()

	// Create a couple servers, and start serving.
	server1 := makeServer()
	server2 := makeServer()

	// This is how to wait for a shutdown.  In this example, a shutdown
	// comes from a signal or a stop command.
	var done sync.WaitGroup
	done.Add(1)

	// This is how to configure signal handling to allow clean shutdown.
	sigChan := make(chan os.Signal, 2)
	signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)

	// This is how to configure handling of stop commands to allow clean
	// shutdown.
	stopChan := make(chan string, 2)
	r.AppCycle().WaitForStop(stopChan)

	// Blocking is used to prevent the process from exiting upon receiving a
	// second signal or stop command while critical cleanup code is
	// executing.
	var blocking sync.WaitGroup
	blockingCh := make(chan struct{})

	// This is how to wait for a signal or stop command and initiate the
	// clean shutdown steps.
	go func() {
		// First signal received.
		select {
		case sig := <-sigChan:
			// If the developer wants to take different actions
			// depending on the type of signal, they can do it here.
			fmt.Fprintln(stdout, "Received signal", sig)
		case stop := <-stopChan:
			fmt.Fprintln(stdout, "Stop", stop)
		}
		// This commences the cleanup stage.
		done.Done()
		// Wait for a second signal or stop command, and force an exit,
		// but only once all blocking cleanup code (if any) has
		// completed.
		select {
		case <-sigChan:
		case <-stopChan:
		}
		<-blockingCh
		os.Exit(signals.DoubleStopExitCode)
	}()

	// This communicates to the parent test driver process in our unit test
	// that this server is ready and waiting on signals or stop commands.
	// It's purely an artifact of our test setup.
	fmt.Fprintln(stdout, "Ready")

	// Wait for shutdown.
	done.Wait()

	// Stop the servers.  In this example we stop them in goroutines to
	// parallelize the wait, but if there was a dependency between the
	// servers, the developer can simply stop them sequentially.
	var waitServerStop sync.WaitGroup
	waitServerStop.Add(2)
	go func() {
		server1.Stop()
		waitServerStop.Done()
	}()
	go func() {
		server2.Stop()
		waitServerStop.Done()
	}()
	waitServerStop.Wait()

{'fraction_non_alphanumeric': 0.11612903225806452, 'fraction_numerical': 0.0025583982202447165, 'mean_word_length': 3.5317540322580645, 'pattern_counts': {'":': 6, '<': 15, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4218964', 'n_tokens_mistral': 3050, 'n_tokens_neox': 2816, 'n_words': 1012}