CS111: Scribe notes for Thursday, April 19, 2012
Written by: Arthur Wolf, Emily Li, and Shuang Xu
(leftover from Tuesday's lecture):
int fd = opentemp(~~~~)
	*no filename
Advantages (of being a syscall):
+ The Operating System can decide where to put file
eg. /dev/shm vs /tmp on SEASnet linux servers
+ The Operating System can free file space automatically when the application exits
+ The Operating System doesn't need to guarantee persistence
-- Persistence means the program could do optimization. There is less "error safe coding", meaning better performance
Disadvantage:
- Can approximate by using random file names in /tmp, open O_EXCL, unlink
(sysadmins can't easily see file)
- lsof: can show a system administrator all open processes
(end of leftovers)


Why signals? or rare unexpected events

eg. power failure typically:

Power diagram

Ways to address the problem:
  1. The Operating System can save a snapshot of all current processes, states, etc. into a persistant file while will be restored on reboot
    Problems:
  2. OS kernel notifies each process of pending doom
  3. A hybrid approach between Approach 1 (OS save snapshot) and Approach 2 (OS kernel notification)
    /dev/power:
    	read from /dev/power
    		  you hang
    		when read returns, power is low
    	- little CPU time --> no polling, just waiting
    

How the kernel can notify apps
/dev/power:
	cat /dev/power -- outputs decimal integer = $ of seconds until power failure (-1 if unknown)

Signals

signals:processes::interrupts:hardware

- Signals will notify a process of external information (eg. power failure, ^C, etc.)
-----A "trap" is sent to a signal handler to make the precess exit.
-----This can happen at any time.

- Interrupts will notify the kernel of external information (ie. information that is external to the kernel)
-----This can happen at any time in kernel or in the user application
-----Control is transferred to an Interrupt Service Routine (ISR)

int kill(pid_t pid, int sig);
	- pid: any of your "processes"
	Some exceptions:
		$ passwd eggert  (setuid root)
		- new password ^C
		I have controlling terminal
#include <signal.h>
	inside, has
	#define SIGWR 29
	$ kill -s PWR 2716

Example signals:

From outside world: From hardware or kernel:
Memory Layout

void *malloc(size_t size) {
	void *p = htop;
	htop += size;
	return p;
}

Signals are easier than pipes
Recipients do not need to be informed beforehand


Problems with signals
Blocking signals
int sigprocmask (int how, sigset_t const *restrict set, sigset_t *restrict oset);
int main (void) {
	signal (SIGPWR, handle_power_failure);
	sigset_t oset;
	//sort some stuff
	sigprocmask (SIG_BLOCK, set, &oset);
		//set: arrage for this set to contain PWR
	printf("size = %d\n",s);
	sigprocmask (SIG_SETMASK, &oset, NULL);
		// with sigprocmask(), when call printf, block PWR signal
}
-----> But this method would be annoying
Another fix:
in void handle_power_failure(),
change printf to
write(2, "ouch", 5);
Write is a syscall. It is async-signal-safe, meaning it can run with other functions and won't crash.
Examples of unsafe (library calls): Examples of safe (low level calls):
EXAMPLE: gzip internals
$gzip foo		--> creates foo.gz
			^C user wants this "atomic"
internally:
	fd1 = open("foo", O_REDONLY);
	fd2 = open("foo.gz", O_WRONLY | O_CREAT, 0666);
	read/write
(--> ^C would create partial.gz)
	close
	unlink("foo");
Add signal (SIGINT, cleanup); after fd1
void cleanup (int) {
	unlink("foo.gz");
	exit(1);
}
-----> But there is a race condition if we have a signal right after the unlink("foo");
Would also need to block/ignore. IE. right before unlink("foo");, put signal (SIGINT, SIGIGN);

But there is still another race condition present, which will be left for students to think about.