v2rayA/v2rayA · warning
getProcessInfo: %w
Error message
getProcessInfo: %w
What it means
getProcessInfo reads /proc/<pid>/stat to extract the process name and PPID; if the read fails it wraps the OS error as 'getProcessInfo: %w' and returns zero values. Because the function returns named values, callers may silently receive empty pn/ppid — the error is created but NOT returned to callers, so it mostly shows up as lost error information plus empty process names.
Source
Thrown at service/common/netTools/netstat/netstat_unix.go:214
func getProcName(s string) string {
i := strings.Index(s, "(")
if i < 0 {
return ""
}
s = s[i+1:]
j := strings.LastIndex(s, ")")
if j < 0 {
return ""
}
return s[:j]
}
func getProcessInfo(pid string) (pn string, ppid string) {
p := filepath.Join(pathProc, pid, "stat")
b, err := os.ReadFile(p)
if err != nil {
err = fmt.Errorf("getProcessInfo: %w", err)
return
}
sp := bytes.Fields(b)
pn = string(sp[1])
return getProcName(pn), string(sp[3])
}
func isProcessSocket(pid string, socketInode map[string]struct{}) string {
// link name is of the form socket:[5860846]
p := filepath.Join(pathProc, pid, "fd")
f, err := os.Open(p)
fns, err := f.Readdirnames(-1)
f.Close()
if err != nil {
return ""
}
for _, fn := range fns {
lk, err := os.Readlink(filepath.Join(p, fn))View on GitHub (pinned to 71e5442fc5)
Solutions
- Accept empty results for vanished PIDs — rescan; transient races are the most common cause.
- Run with privileges or relax hidepid so /proc/<pid>/stat of other users is readable.
- Note the library bug: getProcessInfo assigns err but never returns it, so callers can't distinguish 'no such process' from 'not matched'; patch it to return an error if you need fidelity.
- Verify with 'cat /proc/<pid>/stat' as the service user to confirm accessibility.
Example fix
// before (library code): error swallowed
b, err := os.ReadFile(p)
if err != nil {
err = fmt.Errorf("getProcessInfo: %w", err)
return // err assigned but never propagated
}
// after: propagate properly
func getProcessInfo(pid string) (pn, ppid string, err error) {
b, err := os.ReadFile(filepath.Join(pathProc, pid, "stat"))
if err != nil { return "", "", fmt.Errorf("getProcessInfo: %w", err) }
...
} Defensive patterns
Strategy: retry
Validate before calling
func statReadable(pid string) bool {
f, err := os.Open(filepath.Join("/proc", pid, "stat"))
if err != nil { return false }
f.Close()
return true
} Type guard
func processInfoValid(pn, ppid string) bool { return pn != "" && ppid != "" } Try / catch
pn, ppid := getProcessInfo(pid) // note: error is swallowed by the library
if pn == "" {
time.Sleep(50 * time.Millisecond)
pn, ppid = getProcessInfo(pid) // retry once: PID may have raced away
}
Prevention
- Retry scans — /proc/<pid>/stat reads race with process exit on busy systems.
- Run privileged or relax hidepid so other users' stat files are readable.
- Know the library flaw: getProcessInfo never returns its error, so empty name means 'unreadable or gone' — verify with /proc/<pid>/comm when it matters.
- Ignore kernel-thread PIDs (empty comm) instead of treating them as failures.
When it happens
Trigger: A PID directory listed by findProcessID/FillProcesses/Process disappears (process exits) between ReadDir and the stat read; permission denied on /proc/<pid>/stat for other users' processes (hidepid); kernel threads or zombie entries with unreadable stat.
Common situations: Race-heavy scans on busy systems where PIDs churn; unprivileged user scanning root-owned processes under hidepid=2; PID namespaces mismatch in containers; short-lived processes exiting during the scan.
Related errors
- process not found, correspond socket was freed
- parseAddr: Bad formatted string
- parseAddr: %w
- cannot open the directory /proc
- process not found
AI-assisted analysis of v2rayA/v2rayA@71e5442fc5 (2026-09-05).
Data as JSON: /api/errors/1b64ab61ef18411c.
Report an issue: GitHub.