mirror of
https://github.com/containers/podman.git
synced 2026-03-23 09:02:06 -04:00
When running podman top, the processes collected can exit befor psgo gets information on the processes. This can cause some weird errors and creates some CI flakes. psgo now properly ignores this situation rather then returning errors Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
128 lines
2.8 KiB
Go
128 lines
2.8 KiB
Go
// Copyright 2018 psgo authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package dev
|
|
|
|
import (
|
|
"os"
|
|
"strings"
|
|
"syscall"
|
|
)
|
|
|
|
// TTY represents a tty including its minor and major device number and the
|
|
// path to the tty.
|
|
type TTY struct {
|
|
// Minor device number.
|
|
Minor uint64
|
|
// Major device number.
|
|
Major uint64
|
|
// Path to the tty device.
|
|
Path string
|
|
}
|
|
|
|
// cache TTYs to avoid redundant lookups
|
|
var devices *[]TTY
|
|
|
|
// FindTTY return the corresponding TTY to the ttyNr or nil of non could be
|
|
// found.
|
|
func FindTTY(ttyNr uint64) (*TTY, error) {
|
|
// (man 5 proc) The minor device number is contained in the combination
|
|
// of bits 31 to 20 and 7 to 0; the major device number is in bits 15
|
|
// to 8.
|
|
maj := (ttyNr >> 8) & 0xFF
|
|
min := (ttyNr & 0xFF) | ((ttyNr >> 20) & 0xFFF)
|
|
|
|
if devices == nil {
|
|
devs, err := getTTYs()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
devices = devs
|
|
}
|
|
|
|
for _, t := range *devices {
|
|
if t.Minor == min && t.Major == maj {
|
|
return &t, nil
|
|
}
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
// majDevNum returns the major device number of rdev (see stat_t.Rdev).
|
|
func majDevNum(rdev uint64) uint64 {
|
|
return (rdev >> 8) & 0xfff
|
|
}
|
|
|
|
// minDevNum returns the minor device number of rdev (see stat_t.Rdev).
|
|
func minDevNum(rdev uint64) uint64 {
|
|
return (rdev & 0xff) | ((rdev >> 12) & 0xfff00)
|
|
}
|
|
|
|
// getTTYs parses /dev for tty and pts devices.
|
|
func getTTYs() (*[]TTY, error) {
|
|
devDir, err := os.Open("/dev/")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer devDir.Close()
|
|
|
|
devices := []string{}
|
|
devTTYs, err := devDir.Readdirnames(0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, d := range devTTYs {
|
|
if !strings.HasPrefix(d, "tty") {
|
|
continue
|
|
}
|
|
devices = append(devices, "/dev/"+d)
|
|
}
|
|
|
|
devPTSDir, err := os.Open("/dev/pts/")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer devPTSDir.Close()
|
|
|
|
devPTSs, err := devPTSDir.Readdirnames(0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, d := range devPTSs {
|
|
devices = append(devices, "/dev/pts/"+d)
|
|
}
|
|
|
|
ttys := []TTY{}
|
|
for _, dev := range devices {
|
|
fi, err := os.Stat(dev)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
// catch race conditions
|
|
continue
|
|
}
|
|
return nil, err
|
|
}
|
|
s := fi.Sys().(*syscall.Stat_t)
|
|
t := TTY{
|
|
Minor: minDevNum(s.Rdev),
|
|
Major: majDevNum(s.Rdev),
|
|
Path: dev,
|
|
}
|
|
ttys = append(ttys, t)
|
|
}
|
|
|
|
return &ttys, nil
|
|
}
|