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.