Revision a01b500b lib/utils.py

b/lib/utils.py
844 844
        raise errors.TypeEnforcementError(msg)
845 845

  
846 846

  
847
def _GetProcStatusPath(pid):
848
  """Returns the path for a PID's proc status file.
849

  
850
  @type pid: int
851
  @param pid: Process ID
852
  @rtype: string
853

  
854
  """
855
  return "/proc/%d/status" % pid
856

  
857

  
847 858
def IsProcessAlive(pid):
848 859
  """Check if a given pid exists on the system.
849 860

  
......
870 881
  if pid <= 0:
871 882
    return False
872 883

  
873
  proc_entry = "/proc/%d/status" % pid
874 884
  # /proc in a multiprocessor environment can have strange behaviors.
875 885
  # Retry the os.stat a few times until we get a good result.
876 886
  try:
877
    return Retry(_TryStat, (0.01, 1.5, 0.1), 0.5, args=[proc_entry])
887
    return Retry(_TryStat, (0.01, 1.5, 0.1), 0.5,
888
                 args=[_GetProcStatusPath(pid)])
878 889
  except RetryTimeout, err:
879 890
    err.RaiseInner()
880 891

  
881 892

  
893
def _ParseSigsetT(sigset):
894
  """Parse a rendered sigset_t value.
895

  
896
  This is the opposite of the Linux kernel's fs/proc/array.c:render_sigset_t
897
  function.
898

  
899
  @type sigset: string
900
  @param sigset: Rendered signal set from /proc/$pid/status
901
  @rtype: set
902
  @return: Set of all enabled signal numbers
903

  
904
  """
905
  result = set()
906

  
907
  signum = 0
908
  for ch in reversed(sigset):
909
    chv = int(ch, 16)
910

  
911
    # The following could be done in a loop, but it's easier to read and
912
    # understand in the unrolled form
913
    if chv & 1:
914
      result.add(signum + 1)
915
    if chv & 2:
916
      result.add(signum + 2)
917
    if chv & 4:
918
      result.add(signum + 3)
919
    if chv & 8:
920
      result.add(signum + 4)
921

  
922
    signum += 4
923

  
924
  return result
925

  
926

  
927
def _GetProcStatusField(pstatus, field):
928
  """Retrieves a field from the contents of a proc status file.
929

  
930
  @type pstatus: string
931
  @param pstatus: Contents of /proc/$pid/status
932
  @type field: string
933
  @param field: Name of field whose value should be returned
934
  @rtype: string
935

  
936
  """
937
  for line in pstatus.splitlines():
938
    parts = line.split(":", 1)
939

  
940
    if len(parts) < 2 or parts[0] != field:
941
      continue
942

  
943
    return parts[1].strip()
944

  
945
  return None
946

  
947

  
948
def IsProcessHandlingSignal(pid, signum, status_path=None):
949
  """Checks whether a process is handling a signal.
950

  
951
  @type pid: int
952
  @param pid: Process ID
953
  @type signum: int
954
  @param signum: Signal number
955
  @rtype: bool
956

  
957
  """
958
  if status_path is None:
959
    status_path = _GetProcStatusPath(pid)
960

  
961
  try:
962
    proc_status = ReadFile(status_path)
963
  except EnvironmentError, err:
964
    # In at least one case, reading /proc/$pid/status failed with ESRCH.
965
    if err.errno in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL, errno.ESRCH):
966
      return False
967
    raise
968

  
969
  sigcgt = _GetProcStatusField(proc_status, "SigCgt")
970
  if sigcgt is None:
971
    raise RuntimeError("%s is missing 'SigCgt' field" % status_path)
972

  
973
  # Now check whether signal is handled
974
  return signum in _ParseSigsetT(sigcgt)
975

  
976

  
882 977
def ReadPidFile(pidfile):
883 978
  """Read a pid from a file.
884 979

  

Also available in: Unified diff