# Sesje w NetBSD ## [`struct session`](http://bxr.su/NetBSD/sys/sys/proc.h#104) ```clike /* * One structure allocated per session. */ struct session { int s_count; /* Ref cnt; pgrps in session */ u_int s_flags; #define S_LOGIN_SET 1 /* s_login set in this session */ struct proc *s_leader; /* Session leader */ struct vnode *s_ttyvp; /* Vnode of controlling terminal */ struct tty *s_ttyp; /* Controlling terminal */ char s_login[MAXLOGNAME]; /* Setlogin() name */ pid_t s_sid; /* Session ID (pid of leader) */ }; ``` Dodatkowo [`struct pgrp`](http://bxr.su/NetBSD/sys/sys/proc.h#118) ma wskaźnik na sesję. Wewnętrzny interfejs do zarządzania sesjami ogranicza się do procedur [`proc_sesshold`](http://bxr.su/NetBSD/sys/kern/kern_proc.c#545) i [`proc_sessrele`](http://bxr.su/NetBSD/sys/kern/kern_proc.c#553) obsługujących licznik referencji. ## Zewnętrzny interfejs (syscalle/funkcje z libc) ### `setsid` (funkcja [`sys_setsid`](http://bxr.su/NetBSD/sys/kern/kern_prot.c#244)) #### Semantyka Tworzy nową sesję i grupę procesów. Wywołujący proces staję się liderem nowej sesji i liderem nowej grupy procesów oraz nie ma sterującego terminala. Wywołujący proces jest jedynym procesem w nowej sesji i grupie procesów. Po pomyślnym wykonaniu, zwraca ID nowej grupy procesów, które jest równe PID wywołującego procesu. #### Błędy ##### `EPERM` Wywołujący proces jest już liderem grupy procesów, lub PGID jakiegoś procesu innego niż proces wywołujący jest równe PID procesu wywołującego. #### Uwagi - Ograniczenie do procesów niebędących liderem grupy procesów bierze się stąd, że gdyby proces był liderem jakiejś grupy, to nie można by było stworzyć nowej grupy procesów, której liderem byłby wywołujący proces, bo istnieje już grupa o ID równym PID wywołującego procesu. (Według POSIX lider grupy procesów to proces, którego PID jest równy ID grupy. Stąd wniosek, że proces może być liderem najwyżej jednej grupy procesów.) #### Przegląd implementacji - `sys_setsid` woła [`proc_enterpgrp`](http://bxr.su/NetBSD/sys/kern/kern_proc.c#893), które wykonuje całą robotę. ### `getsid` #### Semantyka `sys_getsid(p)` zwraca ID sesji, w której znajduje się proces o PID `p` lub wywołujący proces jeśli `p == 0`. ID sesji jest zdefiniowane jako PGID lidera sesji. #### Błędy ##### ESRCH Nie znaleziono procesu o podanym ID. ## Interakcje sesji z innymi syscallami ### `setpgrp` - Proces, którego PGID zmieniamy musi być w tej samej sesji co my i nie może być liderem sesji. - Docelowe PGID musi być ID grupy, która już istnieje w sesji, w której znajduje się wywołujący proces, lub musi być równe ID wywołującego procesu. ### `kill` - Zawsze dozwolone jest wysłanie `SIGCONT` do procesu w tej samej sesji, niezależnie od innych wymogów bezpieczeństwa. ### `exit` - Jeśli wywołujący proces jest liderem sesji i sesja ma terminal sterujący, to terminal przestaje być skojarzony z sesją. ### `exec` - Nowy proces dziedziczy po wywołującym procesie sesję. ### `getpgid` - Proces docelowy musi być w tej samej sesji co proces wywołujący. # Job Control ## Definicje z POSIXa #### Session > A collection of process groups established for job control purposes. Each process group is a member of a session. A process is considered to be a member of the session of which its process group is a member. A newly created process joins the session of its creator. A process can alter its session membership; see setsid(). There can be multiple process groups in the same session. #### Session Leader > A process that has created a session. #### Controlling Terminal > A terminal that is associated with a session. Each session may have at most one controlling terminal associated with it, and a controlling terminal is associated with exactly one session. Certain input sequences from the controlling terminal cause signals to be sent to all processes in the foreground process group associated with the controlling terminal. #### Controlling Process > The session leader that established the connection to the controlling terminal. If the terminal subsequently ceases to be a controlling terminal for this session, the session leader ceases to be the controlling process. #### Foreground Process Group (or Foreground Job) > A process group whose member processes have certain privileges, denied to processes in background process groups, when accessing their controlling terminal. Each session that has established a connection with a controlling terminal has at most one process group of the session as the foreground process group of that controlling terminal. #### Background Process Group (or Background Job) > Any process group, other than a foreground process group, that is a member of a session that has established a connection with a controlling terminal. ## Osierocone grupy procesów #### [Definicja](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_264) (POSIX): > A process group in which the parent of every member is either itself a member of the group or is not a member of the group's session. Trochę więcej kontekstu: >Historical implementations have a concept of an orphaned process, which is a process whose parent process has exited. When job control is in use, it is necessary to prevent processes from being stopped in response to interactions with the terminal after they no longer are controlled by a job control-cognizant program. Because signals generated by the terminal are sent to a process group and not to individual processes, and because a signal may be provoked by a process that is not orphaned, but sent to another process that is orphaned, it is necessary to define an orphaned process group. The definition assumes that a process group will be manipulated as a group and that the job control-cognizant process controlling the group is outside of the group and is the parent of at least one process in the group (so that state changes may be reported via waitpid()). Therefore, a group is considered to be controlled as long as at least one process in the group has a parent that is outside of the process group, but within the session. This definition of orphaned process groups ensures that a session leader's process group is always considered to be orphaned, and thus it is prevented from stopping in response to terminal signals. #### Ze specyfikacji [`_Exit`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html) w POSIX: > If the exit of the process causes a process group to become orphaned, and if any member of the newly-orphaned process group is stopped, then a SIGHUP signal followed by a SIGCONT signal shall be sent to each process in the newly-orphaned process group. > The termination of a process may cause a process group to become orphaned in either of two ways. The connection of a process group to its parent(s) outside of the group depends on both the parents and their children. Thus, a process group may be orphaned by the termination of the last connecting parent process outside of the group or by the termination of the last direct descendant of the parent process(es). In either case, if the termination of a process causes a process group to become orphaned, processes within the group are disconnected from their job control shell, which no longer has any information on the existence of the process group. Stopped processes within the group would languish forever. In order to avoid this problem, newly orphaned process groups that contain stopped processes are sent a SIGHUP signal and a SIGCONT signal to indicate that they have been disconnected from their session. The SIGHUP signal causes the process group members to terminate unless they are catching or ignoring SIGHUP. Under most circumstances, all of the members of the process group are stopped if any of them are stopped. > The action of sending a SIGHUP and a SIGCONT signal to members of a newly orphaned process group is similar to the action of 4.2 BSD, which sends SIGHUP and SIGCONT to each stopped child of an exiting process. If such children exit in response to the SIGHUP, any additional descendants receive similar treatment at that time. In this volume of POSIX.1-2017, the signals are sent to the entire process group at the same time. Also, in this volume of POSIX.1-2017, but not in 4.2 BSD, stopped processes may be orphaned, but may be members of a process group that is not orphaned; therefore, the action taken at _exit() must consider processes other than child processes. > It is possible for a process group to be orphaned by a call to setpgid() or setsid(), as well as by process termination. This volume of POSIX.1-2017 does not require sending SIGHUP and SIGCONT in those cases, because, unlike process termination, those cases are not caused accidentally by applications that are unaware of job control. An implementation can choose to send SIGHUP and SIGCONT in those cases as an extension; such an extension must be documented as required in <signal.h>. #### [Kwestia dostępu do terminala sterującego](https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap11.html#tag_21_11_01_04) > If the process calling read() or write() is in a background process group that is orphaned, it is not desirable to stop the process group, as it is no longer under the control of a job control shell that could put it into the foreground again. Accordingly, calls to read() or write() functions by such processes receive an immediate error return. This is different from 4.2 BSD, which kills orphaned processes that receive terminal stop signals. #### Jak to jest w NetBSD - Pole `pg_jobc` w `struct pgrp` liczy procesy w grupie posiadające rodzica w tej samej sesji, ale w innej grupie procesów. - `pg_jobc` może się zmieniać przy wchodzeniu i wychodzeniu procesów z grup. - Ważne procedury: -- [`fixjobc`](http://bxr.su/NetBSD/sys/kern/kern_proc.c#1169): wywoływane przy zmianie grupy procesów i przy śmierci procesu -- [`orphanpg`](http://bxr.su/NetBSD/sys/kern/kern_proc.c#1216): wywoływane gdy `pg_jobc` spadnie do 0. Do każdego zatrzymanego procesu w grupie wysyłany jest `SIGHUP` i `SIGCONT`.