<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://homeostasis.scs.carleton.ca/wiki/index.php?action=history&amp;feed=atom&amp;title=Operating_Systems_2020W_Lecture_7</id>
	<title>Operating Systems 2020W Lecture 7 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://homeostasis.scs.carleton.ca/wiki/index.php?action=history&amp;feed=atom&amp;title=Operating_Systems_2020W_Lecture_7"/>
	<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2020W_Lecture_7&amp;action=history"/>
	<updated>2026-06-02T22:27:53Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2020W_Lecture_7&amp;diff=22572&amp;oldid=prev</id>
		<title>Soma: Created page with &quot;==Video==  Video for the lecture given on January 29, 2020 [https://homeostasis.scs.carleton.ca/~soma/os-2020w/lectures/comp3000-2020w-lec07-20200129.m4v is now available].  =...&quot;</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2020W_Lecture_7&amp;diff=22572&amp;oldid=prev"/>
		<updated>2020-03-20T02:33:03Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==Video==  Video for the lecture given on January 29, 2020 [https://homeostasis.scs.carleton.ca/~soma/os-2020w/lectures/comp3000-2020w-lec07-20200129.m4v is now available].  =...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==Video==&lt;br /&gt;
&lt;br /&gt;
Video for the lecture given on January 29, 2020 [https://homeostasis.scs.carleton.ca/~soma/os-2020w/lectures/comp3000-2020w-lec07-20200129.m4v is now available].&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
&lt;br /&gt;
Topics&lt;br /&gt;
* Assignment 1&lt;br /&gt;
* Signals&lt;br /&gt;
* setuid&lt;br /&gt;
* login process&lt;br /&gt;
&lt;br /&gt;
(others moved to Friday)&lt;br /&gt;
&lt;br /&gt;
===In Class===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Lecture 7&lt;br /&gt;
---------&lt;br /&gt;
&lt;br /&gt;
UNIX signals&lt;br /&gt;
 - messages received by a process, sent by another process or the kernel&lt;br /&gt;
 - used to pause or terminate process, and to report error conditions&lt;br /&gt;
   (memory access errors, divide by zero, etc)&lt;br /&gt;
&lt;br /&gt;
 - you can send signals using the kill command (which makes a kill system call)&lt;br /&gt;
   - by default, sends SIGTERM&lt;br /&gt;
&lt;br /&gt;
 - sorry for no subtitles, will try to set up soon.  Also will see if zoom&lt;br /&gt;
   helps with audio&lt;br /&gt;
&lt;br /&gt;
 - can send any signal with kill, that&amp;#039;s what it is for&lt;br /&gt;
   - but what they do depends on who you are, what privileges you have&lt;br /&gt;
   - is the way you send a signal&lt;br /&gt;
&lt;br /&gt;
 - for example, regular users can&amp;#039;t terminate processes running as other&lt;br /&gt;
   users (can&amp;#039;t send SIGTERM or SIGKILL)&lt;br /&gt;
   - the root user can terminate any process (send signals to all processes)&lt;br /&gt;
&lt;br /&gt;
 - signal handlers are a bit weird&lt;br /&gt;
   - regular functions, but...&lt;br /&gt;
   - they can run at any time&lt;br /&gt;
   - they are called directly by the kernel&lt;br /&gt;
   - they pause regular execution (which resumes after the signal handler&lt;br /&gt;
     finishes)&lt;br /&gt;
&lt;br /&gt;
 - the C library registers default signal handlers&lt;br /&gt;
   - they mostly just terminate the process when a signal is received&lt;br /&gt;
 - you can register your own for *most* signals&lt;br /&gt;
   - except SIGKILL and SIGSTOP  (&amp;quot;force quit&amp;quot; and pause/stop)&lt;br /&gt;
     so you can&amp;#039;t change what happens with them&lt;br /&gt;
&lt;br /&gt;
   - but the rest, you can control by registering a signal handler for&lt;br /&gt;
     that signal.  Afterwards, your code will be called when your process&lt;br /&gt;
     receives that signal&lt;br /&gt;
      - your signal handler can ignore the signal&lt;br /&gt;
      - thus, for SIGSEGV, you can just ignore and have your program continue&lt;br /&gt;
&lt;br /&gt;
   - if you want to send a signal for an application-specific purpose,&lt;br /&gt;
     use SIGUSR1 and SIGUSR2, that is what they are there for&lt;br /&gt;
   - you cannot define your own signals, they are defined by the kernel&lt;br /&gt;
&lt;br /&gt;
 - signals introduce a weird form of concurrency in single-threaded UNIX&lt;br /&gt;
   processes&lt;br /&gt;
     - signal handlers can be called at any time, pausing whatever is currently&lt;br /&gt;
       going on&lt;br /&gt;
     - so if a signal handler modifies shared data structures or state&lt;br /&gt;
       it can corrupt ongoing work&lt;br /&gt;
     - basic rule: make sure signal handlers do as little as possible&lt;br /&gt;
       and don&amp;#039;t interfere&lt;br /&gt;
     - even printing things out isn&amp;#039;t recommended from a signal handler&lt;br /&gt;
       (that&amp;#039;s I/O)&lt;br /&gt;
&lt;br /&gt;
 - if signals can happen at anytime, that means they can also happen&lt;br /&gt;
   while a process is doing a system call&lt;br /&gt;
 - so, what happens to the system call?&lt;br /&gt;
     - option 1: system call is cancelled, returns an error&lt;br /&gt;
     - option 2: system call is paused then resumed&lt;br /&gt;
     - option 3: system call completes *then* signal handler is run&lt;br /&gt;
 - in reality, 1 or 3 is what happens, but sometimes we simulate 2&lt;br /&gt;
     - simulated by setting SA_RESTART option in sigaction&lt;br /&gt;
     - (this is the default behavior on BSD systems)&lt;br /&gt;
     - means a read or sleep will continue even if interrupted by a signal&lt;br /&gt;
        - signal handler runs&lt;br /&gt;
        - system call returns with error saying it was interrupted by a signal&lt;br /&gt;
        - library code calls system call again&lt;br /&gt;
 - for example, consider sleep and read (say for terminal input)&lt;br /&gt;
     - interrupted by signals, cause signal handler to be run&lt;br /&gt;
       then system call returns immediately (before sleep has finished&lt;br /&gt;
       or data has been read)&lt;br /&gt;
 - running a signal handler is an old fashioned way of handling an exception&lt;br /&gt;
     - before there were exceptions, there were signals&lt;br /&gt;
     - low-level exceptions are based on signals (e.g., divide by zero)&lt;br /&gt;
&lt;br /&gt;
 - (and yes they kind of look like hardware interrupts, they are pure software&lt;br /&gt;
    but design is like interrupt handlers)&lt;br /&gt;
&lt;br /&gt;
 - signals are relatively lightweight as far as IPC goes&lt;br /&gt;
     - but don&amp;#039;t use them for performance-critical tasks, other&lt;br /&gt;
       mechanisms are much safer and more reliable&lt;br /&gt;
&lt;br /&gt;
 - signals are specialized, not a general mechanism&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
 - when you type some special characters into a terminal they generate&lt;br /&gt;
   (by default) signals&lt;br /&gt;
     Ctrl-C generates SIGINT (I think)&lt;br /&gt;
     Ctrl-Z generates SIGSTOP&lt;br /&gt;
&lt;br /&gt;
 - sigchld is sent to a process when a child process terminates&lt;br /&gt;
   - so parent doesn&amp;#039;t have to call wait() and wait around, it&lt;br /&gt;
     can do its own thing and call wait() in a signal handler&lt;br /&gt;
     for SIGCHLD&lt;br /&gt;
&lt;br /&gt;
 - all processes are listening to all signals&lt;br /&gt;
   - most just have default handlers defined by the C library&lt;br /&gt;
   - not quite sure what happens if you don&amp;#039;t define a handler&lt;br /&gt;
     (e.g., if you bypass the C library)&lt;br /&gt;
&lt;br /&gt;
 - when any process terminates, its parent must call wait to&lt;br /&gt;
   get its return value (otherwise it turns into a zombie)&lt;br /&gt;
 - if the parent goes away, there is always the parent of last resort:&lt;br /&gt;
   init (PID 1)&lt;br /&gt;
 - init always calls wait in response to SIGCHLD&lt;br /&gt;
 - if init terminates, the system shuts down&lt;br /&gt;
&lt;br /&gt;
 - on modern Linux systems, init is part of systemd&lt;br /&gt;
&lt;br /&gt;
 - a zombie process is a process that has terminated but who hasn&amp;#039;t&lt;br /&gt;
   been reaped (waited on by its parent)&lt;br /&gt;
     - it still shows up in the process table with status &amp;quot;Z&amp;quot;&lt;br /&gt;
     - it can&amp;#039;t be killed&lt;br /&gt;
     - can only be eliminated by killing the irresponsible parent&lt;br /&gt;
       - then init will take over and run wait&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
3000login&lt;br /&gt;
 - Q: what happens when you &amp;quot;log in&amp;quot; to a UNIX system?&lt;br /&gt;
&lt;br /&gt;
 - first, have to authenticate (type in your password, do public key based&lt;br /&gt;
   auth, show your face, whatever)&lt;br /&gt;
&lt;br /&gt;
 - after authentication, have to start the user&amp;#039;s session.  How?&lt;br /&gt;
&lt;br /&gt;
 - to a first approximation, it is just like running a command in a shell&lt;br /&gt;
   - except that first &amp;quot;command&amp;quot; has to run as a specific user&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
[https://homeostasis.scs.carleton.ca/~soma/os-2020w/code/3000login.c download 3000login.c]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
/* 3000login.c */&lt;br /&gt;
/* version 0.1 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[], char *envp[])&lt;br /&gt;
{&lt;br /&gt;
        uid_t uid;&lt;br /&gt;
        int result;&lt;br /&gt;
        char *bash_argv[3];&lt;br /&gt;
        &lt;br /&gt;
        if (argc &amp;lt; 2) {&lt;br /&gt;
                fprintf(stderr, &amp;quot;Usage: %s &amp;lt;user ID&amp;gt;\n&amp;quot;, argv[0]);&lt;br /&gt;
                exit(-1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        uid = atoi(argv[1]);&lt;br /&gt;
&lt;br /&gt;
        result = setuid(uid);&lt;br /&gt;
&lt;br /&gt;
        if (result == 0) {&lt;br /&gt;
                fprintf(stderr, &amp;quot;Successfully changed to uid %d\n&amp;quot;, uid);&lt;br /&gt;
                bash_argv[0] = &amp;quot;bash&amp;quot;;&lt;br /&gt;
                bash_argv[1] = &amp;quot;--login&amp;quot;;&lt;br /&gt;
                bash_argv[2] = NULL;&lt;br /&gt;
                execve(&amp;quot;/bin/bash&amp;quot;, bash_argv, envp);&lt;br /&gt;
        } else {&lt;br /&gt;
                fprintf(stderr, &amp;quot;Failed to change to uid %d\n&amp;quot;, uid);&lt;br /&gt;
                exit(-2);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        fprintf(stderr, &amp;quot;Failed to exec bash\n&amp;quot;);&lt;br /&gt;
        return -3;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Soma</name></author>
	</entry>
</feed>