commit 783e21ea9d6ca7572f67668683d6905971146a3a Author: George Suntres Date: Sun Mar 29 11:37:56 2026 -0400 Initial import diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a66ef27 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Allowlisting gitignore template for GO projects prevents us +# from adding various unwanted local files, such as generated +# files, developer configurations or IDE-specific files etc. +# +# Recommended: Go.AllowList.gitignore + +# Ignore everything +* + +# But these files... +!.gitignore + +!*.go +!go.sum +!go.mod + +!README.md +!LICENSE + +!Makefile + +!*.sh +!*.md + +# ...even if they are in subdirectories +!*/ diff --git a/fs.go b/fs.go new file mode 100644 index 0000000..dd7dd64 --- /dev/null +++ b/fs.go @@ -0,0 +1,18 @@ +package sys + +import ( + "runtime" + "path/filepath" +) + +func Rootify(path string) string { + return filepath.Join(GetProjectRoot(), path) +} + +func GetProjectRoot() string { + _, b, _, _ := runtime.Caller(0) + // b is the absolute path to this specific .go file + // 1st Dir() gets the folder containing the file + // 2nd Dir() gets the parent of that folder + return filepath.Dir(filepath.Dir(b)) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..bbedfb0 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.gsuntres.com/gsuntres/sys + +go 1.25.0 diff --git a/main.go b/main.go new file mode 100644 index 0000000..288609c --- /dev/null +++ b/main.go @@ -0,0 +1,54 @@ +package sys + +import ( + "os" + "os/signal" + "syscall" + "sync" + "log" +) + +var onExitMutex sync.Mutex + +var onExitHandlers int + +func init() { + onExitHandlers = 0 +} + +type OnExitFunc func() + +func OnExit(fn OnExitFunc) { + onExitMutex.Lock() + onExitHandlers++ + onExitMutex.Unlock() + + // shutdown hook + c := make(chan os.Signal, 2) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + go func() { + <-c + // ctx, cancel := context.WithTimeout(context.Background(), *wait) + // defer cancel() + // Doesn't block if no connections, but will otherwise wait + // until the timeout deadline. + + log.Println("Calling on exit...") + + // controller.Stop() + fn() + + onExitMutex.Lock() + onExitHandlers-- + onExitMutex.Unlock() + + // Optionally, you could run srv.Shutdown in a goroutine and block on + // <-ctx.Done() if your application should wait for other services + // to finalize based on context cancellation. + + if onExitHandlers == 0 { + log.Println("no more exit handler, will exit") + os.Exit(0) + } + }() +}