osutil.go 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // Copyright 2015 CoreOS, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package osutil
  15. import (
  16. "log"
  17. "os"
  18. "os/signal"
  19. "strings"
  20. "sync"
  21. "syscall"
  22. )
  23. func Unsetenv(key string) error {
  24. envs := os.Environ()
  25. os.Clearenv()
  26. for _, e := range envs {
  27. strs := strings.SplitN(e, "=", 2)
  28. if strs[0] == key {
  29. continue
  30. }
  31. if err := os.Setenv(strs[0], strs[1]); err != nil {
  32. return err
  33. }
  34. }
  35. return nil
  36. }
  37. // InterruptHandler is a function that is called on receiving a
  38. // SIGTERM or SIGINT signal.
  39. type InterruptHandler func()
  40. var (
  41. interruptRegisterMu, interruptExitMu sync.Mutex
  42. // interruptHandlers holds all registered InterruptHandlers in order
  43. // they will be executed.
  44. interruptHandlers = []InterruptHandler{}
  45. )
  46. // RegisterInterruptHandler registers a new InterruptHandler. Handlers registered
  47. // after interrupt handing was initiated will not be executed.
  48. func RegisterInterruptHandler(h InterruptHandler) {
  49. interruptRegisterMu.Lock()
  50. defer interruptRegisterMu.Unlock()
  51. interruptHandlers = append(interruptHandlers, h)
  52. }
  53. // HandleInterrupts calls the handler functions on receiving a SIGINT or SIGTERM.
  54. func HandleInterrupts() {
  55. notifier := make(chan os.Signal, 1)
  56. signal.Notify(notifier, syscall.SIGINT, syscall.SIGTERM)
  57. go func() {
  58. sig := <-notifier
  59. interruptRegisterMu.Lock()
  60. ihs := make([]InterruptHandler, len(interruptHandlers))
  61. copy(ihs, interruptHandlers)
  62. interruptRegisterMu.Unlock()
  63. interruptExitMu.Lock()
  64. log.Printf("received %v signal, shutting down", sig)
  65. for _, h := range ihs {
  66. h()
  67. }
  68. signal.Stop(notifier)
  69. syscall.Kill(syscall.Getpid(), sig.(syscall.Signal))
  70. }()
  71. }
  72. // Exit relays to os.Exit if no interrupt handlers are running, blocks otherwise.
  73. func Exit(code int) {
  74. interruptExitMu.Lock()
  75. os.Exit(code)
  76. }