1 NSPR's position on abrupt thread termination
2 ============================================
4 This memo describes my position on a facility that is currently under
5 discussion for inclusion in the NetScape Portable Runtime (NSPR); the
6 ability of a thread to abruptly exit. I resist including this function
7 in NSPR because it results in bad programming practice and unsupportable
10 *Threads are not processes.*
12 Abrupt termination has been available in the UNIX/C environment for some
13 time (``exit()``), and I assume that the basic semantics defined there
14 are applicable here. In that environment, ``exit()`` may be called and
15 any time, and results in the calling thread's immediate termination. In
16 the situation where it was defined (UNIX), which has only a single
17 thread of execution, that is equivalent to terminating the process. The
18 process abstraction is then responsible for closing all open files and
19 reclaiming all storage that may have been allocated during the process'
22 This practice does not extend to threads. Threads run within the
23 confines of a process (or similar abstractions in other environments).
24 Threads are lightweight because they do not maintain the full protection
25 domain provided by a process. So in a threaded environment, what is the
26 parallel to UNIX' ``exit()``?
28 NSPR has defined a function, callable by any thread within a process at
29 any time, called ``PR_ProcessExit()``. This is identical to UNIX
30 ``exit()`` and was so named in an effort to make the obvious even more
31 so. When called, the process exits, closing files and reclaiming the
34 Certain people have been disappointed when NSPR did not provide a
35 functional equivalent to exit just a particular thread. Apparently they
36 have failed to consider the ramifications. If a thread was to abruptly
37 terminate, there is no recording of what resources it owns and should
38 therefore be reclaimed. Those resources are in fact, owned by the
39 process and shared by all the threads within the process.
41 In the general course of events when programming with threads, it is
42 very advantageous for a thread to have resources that it and only it
43 knows about. In the natural course of events, these resources will be
44 allocated by a thread, used for some period of time, and then freed as
45 the stack unwinds. In these cases, the presence of the data is recorded
46 only on the stack, known only to the single thread (normally referred to
49 The problem with abrupt termination is that it can happen at any time,
50 to a thread that is coded correctly to handle both normal and
51 exceptional situations, but will be unable to do so since it will be
52 denied the opportunity to complete execution. It can happen because it
53 called out of its own scope into some lazily implemented library.
55 NSPR's answer to this is that there is no abrupt thread termination. All
56 threads must unwind and return from their root function. If they cannot,
57 because of some state corruption, then they must assume that the
58 corruption, like the state, is shared, and their only resource is for
59 the process to terminate.
61 To make this solution work requires that a function that encounters an
62 error be designed such that it first repairs its immediate state, and
63 then reports that error to its caller. If the caller cannot deal with
64 the failure, it must do the same. This process continues until the
65 thread either recovers from the malady or returns from the root
66 function. This is not all that difficult (though having done it a number
67 of times to already existing code, I will admit it isn't much fun
70 The implementation of either strategy within the NSPR runtime is not
71 difficult. That is not what this memo is about. This is about providing
72 an API that coaxes people to do the right thing in as many ways as
73 possible. The existence of ``exit()`` in the UNIX/C environment is a
74 perfect example of how programmers will employ the most expediant
75 solution available. The definition of the language C is such that
76 returning from ``main()`` is a perfectly fine thing to do. But what
77 percentage of C programs actually bother? In UNIX, with its complex
78 definition of a protection domain, it happens to work (one might even
79 say it's more efficient) to exit from anywhere. But threads are not
80 processes. If threads have to maintain the same type of resource
81 knowledge as a process, they loose all of their benefit.
83 Threads are an implementation strategy to provide the illusion of
84 concurrency within a process. They are alternatives to large state
85 machines with mostly non-blocking library functions. When the latter is
86 used to provide concurrency, calling ``exit()`` will terminate the
87 entire process. Why would anyone expect a thread to behave differently?
88 Threads are not processes.