Threads

Somewhat like a “lightweight process.”

Creating threads

#include <pthread.h>
int pthread_create(pthread_t* thread, pthread_attr_t const* attr, void* (*start)(void*), void* arg);
void pthread_exit(void* value);
void pthread_join(pthread_t* thread, void** value);
int pthread_kill(pthread_t* t, int sig);
int pthread_cancel(pthread_t* t);

Signal Downsides

Can cause an asynchronous function call to occur at anytime between machine instructions.

Note that instructions are not necessarily atomic.

Signal advice:

  1. Only do simple things inside of a signal handler
int volatile x;
void handle(int sig) { x = 1; }
...
if (x) {
	...
}

volatile makes sure accesses/writes to x are not optimized away

What if you need your handler to not be that small?

void handle(int sig) {
	char* p = malloc(1000);
	*p = q;
	free(p);
}

This is horrible: if calling malloc within the thread, it will destroy the data structure.

Make sure to only call async-signal safe functions.

close is async-signal safe.

printf is not async-signal safe (uses some buffer to putchar)