Sessions
Relevant source files
Purpose and Scope
This document explains the concept of Sessions in the axprocess codebase. A Session represents a collection of Process Groups and forms the top level of the process hierarchy. Each process belongs to exactly one process group, and each process group belongs to exactly one session.
The session abstraction is inspired by Unix-like operating systems, where sessions are typically used to manage groups of related processes, such as those associated with a terminal login session.
Sources: src/session.rs(L12 - L17)
Session Structure
A Session in axprocess is a simple structure that maintains a collection of process groups:
classDiagram note for Session "Each session has a unique session ID (sid)" class Session { sid: Pid process_groups: SpinNoIrq~~ +sid() Pid +process_groups() Vec~ +new(sid: Pid) Arc } class ProcessGroup { pgid: Pid session: Arc processes: WeakMap~ } Session "1" o-- "*" ProcessGroup : contains
The Session
struct contains:
sid
: A unique session ID (of typePid
)process_groups
: A thread-safe weak map that links process group IDs to weak references of process groups
Sessions use weak references to their process groups to avoid reference cycles, as process groups hold strong references to their sessions.
Sources: src/session.rs(L12 - L17) src/session.rs(L19 - L26)
Session Hierarchy
Sessions form the top level of the process management hierarchy in axprocess. Each element in the hierarchy has specific relationships with others:
flowchart TD S["Session"] PG1["Process Group 1"] PG2["Process Group 2"] PG3["Process Group 3"] P1["Process 1"] P2["Process 2"] P3["Process 3"] P4["Process 4"] P5["Process 5"] P6["Process 6"] T1["Thread 1.1"] T2["Thread 1.2"] T3["Thread 4.1"] P1 --> T1 P1 --> T2 P4 --> T3 PG1 --> P1 PG1 --> P2 PG2 --> P3 PG3 --> P4 PG3 --> P5 PG3 --> P6 S --> PG1 S --> PG2 S --> PG3
This hierarchical structure allows for logical grouping of related processes and simplifies operations that need to be performed on sets of processes.
Sources: src/session.rs(L12 - L17) tests/session.rs(L9 - L19)
Memory Management
The session implementation uses a careful reference counting approach to prevent memory leaks and ensure proper cleanup:
flowchart TD subgraph subGraph0["Reference Structure"] P["Process"] PG["Process Group"] S["Session"] PG_ref["Process Group (Reference)"] P_ref["Process (Reference)"] end note["Strong references point upwardWeak references point downward"] P --> PG PG --> P_ref PG --> S S --> PG_ref
Key aspects of memory management for sessions:
- Processes hold strong references to their process groups
- Process groups hold strong references to their sessions
- Sessions hold weak references to their process groups
- This prevents circular references while ensuring objects stay alive as needed
When all processes in a process group are freed, the process group is dropped, and when all process groups in a session are dropped, the session is freed.
Sources: src/session.rs(L15) tests/session.rs(L51 - L64)
Session Creation and Management
Creation
A session is created when a process calls create_session()
. The process becomes the leader of both the new session and a new process group:
sequenceDiagram participant Process as Process participant ProcessGroup as Process Group participant OldProcessGroup as Old Process Group participant NewSession as New Session participant OldSession as Old Session Process ->> Process: create_session() Note over Process: Process must not be a group leader Process ->> NewSession: Session::new(pid) NewSession -->> Process: new session Process ->> ProcessGroup: ProcessGroup::new(pid, &session) ProcessGroup -->> Process: new process group Process ->> OldProcessGroup: leave old group OldProcessGroup -->> OldSession: update group membership Process ->> ProcessGroup: join new group Process -->> Process: return (session, group)
The process must not already be a group leader to create a new session. This is enforced at runtime.
Sources: src/session.rs(L19 - L26) tests/session.rs(L21 - L44) tests/session.rs(L47 - L49)
Session Management
Sessions provide methods to access their properties and process groups:
sid()
: Returns the session IDprocess_groups()
: Returns all process groups that belong to this session
A process cannot move to a process group that belongs to a different session:
Sources: src/session.rs(L29 - L39) tests/session.rs(L86 - L96)
Cleanup
When all processes in a session exit and are freed, the session's process groups will be empty, and eventually, the session itself will be cleaned up through Rust's reference counting mechanism:
sequenceDiagram participant Process as Process participant ProcessGroup as Process Group participant Session as Session Process ->> Process: exit() Process ->> Process: free() Note over Process: Process no longer in group Note over ProcessGroup: When all processes are gone ProcessGroup ->> ProcessGroup: Drop Note over ProcessGroup: Process group removes itself from session Note over Session: When all process groups are gone Session ->> Session: Drop Note over Session: Session is freed
Sources: tests/session.rs(L51 - L64) tests/session.rs(L99 - L108)
Practical Examples
Basic Session Structure
The initial process (init) automatically creates a session and process group:
let init = init_proc();
let group = init.group();
let session = group.session();
// The group and session IDs match the init process ID
assert_eq!(group.pgid(), init.pid());
assert_eq!(session.sid(), init.pid());
Sources: tests/session.rs(L9 - L19)
Creating a New Session
A child process can create its own session:
let parent = init_proc();
let child = parent.new_child();
let (child_session, child_group) = child.create_session().unwrap();
// The child becomes the leader of both the new session and group
assert_eq!(child_group.pgid(), child.pid());
assert_eq!(child_session.sid(), child.pid());
Sources: tests/session.rs(L21 - L44)
Implementation Details
The Session
struct is implemented in src/session.rs with these key methods:
fn new(sid: Pid) -> Arc<Self>
: Creates a new session with the given session IDfn sid(&self) -> Pid
: Returns the session IDfn process_groups(&self) -> Vec<Arc<ProcessGroup>>
: Returns all process groups in this session
The implementation uses SpinNoIrq
locks for thread safety and concurrent access to session data.
Sources: src/session.rs(L19 - L39)
Related Topics
For more information about how process groups interact with sessions, see Process Groups.
For details on how processes move between groups and the hierarchical relationship between sessions, groups, and processes, see Hierarchy and Movement.