Operating Systems: Signals, Scheduling, and Threads


Note: Superscripts refer to code in the Code Appendix at the bottom of this page. Numbers correspond.

(leftover from last lecture: Temporary Files)

int fd = opentemp() Benefits:

This can be approximated by:

Today's Lecture

Handling unexpected events (Power failure, etc)

How the kernel can notify applications

cat/dev/power outputs decimal integer = the number of seconds until power failure (-1 if unknown)

About Signals:


	Example: GZIP 
	$gzip foo
	/*
	* creates foo.gz
	* The user wants this to be atomic, i.e. it will leave either foo or foo.gz but not both
	* these internals would create problems if the user presses ^c.  Both files will be present, but fd2 may be partially complete
	*/
	gzip internals{
		fd1 = open("foo", O_RDONLY);
		fd2 = open("foo.gz", O_WRONLY|O_CREAT, 0666);
		read /write/ close
		unlink
	}
	
	signal(SIGINT, cleanup);
	
	//To fix the error create a signal handler 
	void cleanup(int){
		unlink("foo.gz");
		_exit(1);
	}

Code Appendix

1)


	//pointer to a function that takes an integer as a parameter
	//int is the signal number
	typedef void (*handler)(int);
	 #include <signal.h>
		handler signal(int, handler);
		old handler		new handler	Takes default action
						or 	SIG_IGN
							SIGDFL
	int main (void){
	//when there's a power failure, execute function handle_power_failure
		signal(SIGPWER, handle_power_failure);
		... 
	}

	void handle_power_failure(int sig){
		//save state
		/*the printf command can cause errors, due to the the low level pointer manipulation of printf.  Printf will fail if in between the commands "update buffer pointer" and "update buffer size".  To fix this problem, block signals (different from ignoring) */
		printf("power out! \n");
		exit(1);
	}

2)


	int main (void){
		//when there's a power failure, execute function handle_power_failure
			signal(SIGPWER, handle_power_failure);
			
		/*
		how takes in signals:
			SIGBLOCK
			SIG_SEMASK
			SIG_UNBLOCK
		sigset_t takes one bit per signal
		set is a restricted pointer to a constant sigset_t
		restricted: only way to get to that object from the current system call.  Places a constraint on the caller.  I.e. don't use aliases for this.
		*/
		int sigprocmask(int how, sigset_t const *restrict set, sigset_t *restrict oset);
		//saving the old signal set, preventing the race condition from the previous example (handle_power_failure)
			sigset_t oset;
			//sort some stuff
			sigprocmask(SIG_BLOCK, set, &oset)
			printf("size=%d\n", s);
			sigprocmask(SIG_SETMASK, &oset, NULL);
	}