SwadhyAI Notes

All Operating Systems notes

Start here

Reentrant means a function can be interrupted and entered again safely without hidden per-invocation static state. Thread-safe is broader; async-signal-safe is a tiny POSIX list for signal handlers, stricter still.

Reentrancy vs thread-safety vs async-signal-safety

Reentrant functions avoid static buffers and hidden globals; they work when called recursively or from multiple threads if each call uses only stack parameters. Signal handlers run in a constrained context, calling malloc is unsafe if it might contend with an interrupted malloc.

By the end of this page you should be able to

  1. Give an example of a C library function that is not reentrant and why.
  2. Explain why async-signal-safe is smaller than thread-safe.
  3. Describe how TLS can help separate per-thread state.

Operating systems · Threads

Reentrancy

Safe to interrupt and re-enter

TL;DR

A function is reentrant if it can be called again while an earlier invocation is still in progress **without** relying on a single mutable global in an unsafe way. Reentrancy differs from thread-safety: `strtok` is neither; reentrant versions use explicit state parameters (`strtok_r`).

Summary

Reentrancy matters wherever execution can nest: signals, interrupts, recursive calls, and certain callback chains. Interviewers probe whether you know `strtok_r` vs `strtok` and async-signal-safe lists.

Deeper narrative

Reentrant functions can be interrupted and called again safely without per-invocation static state. Thread-safe is broader; async-signal-safe is narrower still, signal handlers may only call a tiny POSIX subset.

Mechanism (step by step)

Treat each step as a sentence in the story you tell on a whiteboard.
1

Identify saved state

Static locals, hidden globals, errno clobbering in libraries.

2

Prefer pure stack data

Pass context pointers instead of hidden singletons.

3

Locking strategy

Recursive mutexes if same thread may re-enter, otherwise refactor.

4

Signal context

Defer heavy work to thread pool; handler sets atomic flag only.

Key insights

Each card is a compression of the lesson, use them as spaced-repetition prompts.

Pure functions win

No shared mutable state ⇒ naturally reentrant across threads and signals.

Hidden globals

Random number engines, locale, stdio locks, libraries hide global state that breaks reentrancy assumptions.

Recursive mutexes

Allow same thread to re-lock, fixes some reentrancy deadlocks but masks design smells.

Kernel reentrancy

Interrupt handlers must not take sleeping locks, different constraints than user pthread code.

Did you know?

Trivia with teeth: the kind of fact that changes how you reason about a design.
Signal handlers must only call async-signal-safe functions, reentrancy rules are strict.
Per-thread errno avoids cross-thread clobber but not signal handler races without care.
Locking a non-reentrant library from threads serializes calls, sometimes acceptable hotfix.

Common pitfalls

Where smart people still trip, read slowly.

Calling malloc in signal handler

Not async-signal-safe, can deadlock if interrupted mid-allocator lock.

Assuming thread-safe == reentrant

Thread-safe may allocate per-thread state; reentrant forbids hidden contention.

Glossary

Async-signal-safe

Callable from a signal handler without deadlocking libc.

Idempotent

Same effect if applied multiple times, helps retries, not same as reentrant.

Recursive mutex

Same thread may lock again without self-deadlock.

Interview follow-ups

  1. List three POSIX functions that are async-signal-safe.
  2. Why is `strtok` not reentrant?
  3. How does TLS help reentrancy?

Callouts

Signals

Never malloc inside a signal handler unless you know you are async-signal-safe, deadlocks await.

Walkthrough & deep dive

Left: practical “how would I use this?” threads. Right: slower, code-leaning explanations, open one panel at a time so the page does not feel like a wall of sameness.

Walkthrough

Classify

Is `malloc` safe in a signal handler? Why or why not?

Deep dive

Async-signal-safe

POSIX lists tiny subset: `write`, `_exit`, `kill`, many syscalls disallowed because they take locks internally.

Prefer *_r APIs

c
char *save = NULL;
strtok_r(buf, " ", &save);

Self-check

Misses here are cheap; misses in an interview are not. Treat wrong answers as a patch list for tomorrow.

1Reentrant code avoids…

2`strtok` is problematic because…

3Async-signal-safe means…