In many other multithreaded OSs, threads are not processes merely parts
of a parent task. Therefore, the question of "what happens if a thread
calls fork() or (worse) if a thread execve()'s some external program"
becomes problematic: the whole task could be replaced. The POSIX
1c standard defines a thread calling fork() to duplicate only the calling
thread in the new process; and an execve() from a thread would stop all
threads of that process.
Having two different implementations and schedulers for processes is
a flaw that has perpetuated from implementation to implementation. In fact,
some multitasking OSs have opted not to support threads due to these
problems (not to mention the effort needed to make the kernel and libraries
100% reentrant). For example, the POSIX-compliant Windows NT does not to
support threads (Windows NT does support threads but they are not
POSIX compliant).
Most people have a hard enough time understanding tasks, never mind
"chopped up tasks" or threads. The first problem while programming
is answering the question: "What can be threaded in my app?".
That, in itself, can be very laborious (see section on "What
kinds of things should be threaded/multitasked?").
Another problem is locking. All the nightmares about sharing, locking,
deadlock, race conditions, etc. come vividly alive in threads. Processes
don't usually have to deal with this, since most shared data is passed
through pipes. Now, threads can share file handles, pipes, variables, signals,
etc. Trying to test and duplicate error conditions can cause more gray
hair than a wayward child.