pidfile.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /*
  2. Copyright 2025 Docker Compose CLI authors
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. // Package pidfile provides helper functions to create and remove PID files.
  14. // A PID file is usually a file used to store the process ID of a running
  15. // process.
  16. //
  17. // This is a temporary copy of github.com/moby/moby/v2/pkg/pidfile, and
  18. // should be replaced once pidfile is available as a standalone module.
  19. package pidfile
  20. import (
  21. "bytes"
  22. "fmt"
  23. "os"
  24. "strconv"
  25. )
  26. // Read reads the "PID file" at path, and returns the PID if it contains a
  27. // valid PID of a running process, or 0 otherwise. It returns an error when
  28. // failing to read the file, or if the file doesn't exist, but malformed content
  29. // is ignored. Consumers should therefore check if the returned PID is a non-zero
  30. // value before use.
  31. func Read(path string) (pid int, _ error) {
  32. pidByte, err := os.ReadFile(path)
  33. if err != nil {
  34. return 0, err
  35. }
  36. pid, err = strconv.Atoi(string(bytes.TrimSpace(pidByte)))
  37. if err != nil {
  38. return 0, nil
  39. }
  40. if pid != 0 && alive(pid) {
  41. return pid, nil
  42. }
  43. return 0, nil
  44. }
  45. // Write writes a "PID file" at the specified path. It returns an error if the
  46. // file exists and contains a valid PID of a running process, or when failing
  47. // to write the file.
  48. func Write(path string, pid int) error {
  49. if pid < 1 {
  50. return fmt.Errorf("invalid PID (%d): only positive PIDs are allowed", pid)
  51. }
  52. oldPID, err := Read(path)
  53. if err != nil && !os.IsNotExist(err) {
  54. return err
  55. }
  56. if oldPID != 0 {
  57. return fmt.Errorf("process with PID %d is still running", oldPID)
  58. }
  59. return os.WriteFile(path, []byte(strconv.Itoa(pid)), 0o644)
  60. }