Geoff Steckel wrote:
This discussion of threads is isomorphic to:

   Why do CPUs have MMUs?
   Why don't we write "good guys' timeshared programs" which run
      cooperatively and noninterfering in a shared unprotected
      environment?

   Answer: it's too hard to write perfect programs.
      Compartmentalized security simplifies each component and
         drastically simplifies keeping the whole system running well.

Yes, it is.

It's controlled by the code you write.

That makes it implicit and/or accidental. Data sharing between any parties must
be explicit and declared, otherwise it is either a bug now
or a bug later when the next maintainer doesn't know.
Accidental state sharing is by definition a fatal bug.

How is it qualitatively more implicit than IPC?

   they encode state implicitly in the program counters of the threads

The hell?
OK, you're debugging a multithreaded program. Quick, what's the state
of all the threads now? Not encoded in data? Hmmmmmmmmmm.... how long
is it going to take to discover it.

Have you ever had to debug a multi-threaded application? You can use a debugger to check the state just the same.

   they are extremely difficult to guard against external conditions
     such as unexpected incoming data

Incoming from where?
Any useful program does I/O. Otherwise the computer is a space heater.
So, other than pattern generators with built in data, every useful
program must take input. Any multithreaded program which I've observed
has some form of asynchronous inputs. Now, what happens when an unexpected
datum arrives.

So it's expected in the sense that "there is a thread looking for input on this file descriptor." But it's unexpected in the sense of... how?

complete and correct error recovery requires complex and error prone code

Welcome to "non-trivial software development."

That's exactly the point. Subtle but extremely important.
Every effort must be made to keep the software as simple as possible
so that it is comprehensible. Incomprehensible software is by
definition a fatal bug.

The point is that all non-trivial software development has the problem that complete and correct error recovery requires complex and error-prone code?

Any construct which causes complexity disproportionate with the
total system gain (development & maintenance resources, run time resources,
etc. vs useful output) must be avoided.

Finally, something we agree on. Make the code as simple as you can - but no simpler (to paraphrase Einstein). Look, all of these issues - *all* of them - are exactly the sorts of problems that the developers need to get a handle on in order to support the SMP kernel, never mind kernel threads. If they can't get it right, then they might as well say so, and we can all go back to uniprocessor machines for anything secure, and run Linux or FreeBSD for anything performance-sensitive.

Now, I haven't looked at the exact code written, but based on the descriptions I'm guessing it's a worker thread model where discrete units of work are parceled out, performed, and returned. This has got to be the easiest model of threading to get right, the easiest model to verify, and entirely appropriate for the problem described (processing independent blocks).

This is the same model, albeit with better performance characteristics (assuming kernel threads), that Apache uses, and one of the great things about this model is that it's very easy to tightly control what memory threads share. But the response here has been an uninformed kneejerk response to 'threads' and how they're hard to get right, without anyone realizing that this particular model is actually *not* hard to get right.
--
 Matthew Weigel
 hacker
 unique & idempot.ent

Reply via email to