Summary
- OS: Ubuntu 24.04.4 LTS
- Architecture: x86_64
- Psutil version: 6.1.0
- Python version: 3.10.15
- Type: core
Description
Process.terminal() returns None for PTYs allocated after the first call to get_terminal_map() in a given process. In a long-running daemon that calls Process.terminal() (directly or via process_iter(['terminal'])) once before any /dev/pts/N entries exist, every subsequent PTY allocated for the lifetime of that process is invisible — terminal lookups silently return None even when the PTY is right there in /dev/pts/.
Probable cause
psutil._psposix.get_terminal_map() is @memoize'd module-globally with no TTL. The cache is built lazily on first call by globbing /dev/{tty*,pts/*} and stat'ing each entry. /dev/pts/N is a devpts filesystem — entries exist only while a PTY is allocated, so if the cache is built when no PTYs are open, no pts/* entries enter the dict and they never will, regardless of what devpts does later. Process.terminal() then sees the process's tty_nr from /proc/N/stat but the dict lookup misses and returns None.
Summary
Description
Process.terminal()returnsNonefor PTYs allocated after the first call toget_terminal_map()in a given process. In a long-running daemon that callsProcess.terminal()(directly or viaprocess_iter(['terminal'])) once before any/dev/pts/Nentries exist, every subsequent PTY allocated for the lifetime of that process is invisible — terminal lookups silently returnNoneeven when the PTY is right there in/dev/pts/.Probable cause
psutil._psposix.get_terminal_map()is@memoize'd module-globally with no TTL. The cache is built lazily on first call by globbing/dev/{tty*,pts/*}and stat'ing each entry./dev/pts/Nis adevptsfilesystem — entries exist only while a PTY is allocated, so if the cache is built when no PTYs are open, nopts/*entries enter the dict and they never will, regardless of whatdevptsdoes later.Process.terminal()then sees the process'stty_nrfrom/proc/N/statbut the dict lookup misses and returnsNone.