|
|
Useful hints on writing multi-threaded DCE applications:
All DCE applications are multi-threaded — DCE runtime
software is multi-threaded and all DCE applications are
multi-threaded; even if the application code itself does not
explicitly create threads.
Using non-thread-safe libraries — When making calls to
libraries which are not known to be specifically thread-safe, a
locking scheme needs to be provided by the application, For example,
non-thread-safe routines 1 and 2 make a call to routine A (also
non-thread-safe), if routines 1 and 2 use different mutexes to lock
their calls to routine A, then routines 1 and 2 can both get into
routine A at the same time (violating the programmer's attempt to
make the calls thread-safe).
Using fork() in a threaded application —
fork() is not allowed from a threaded task.
environ is a process-wide resource — Programmers must
coordinate threads that use the putenv() and
getenv() interfaces to change and read environ.
Signal mask: A thread-specific resource — If one thread
manipulates the signal mask, it only affects signals that a specific
thread is interested in.
Handling synchronous terminating signals — The default
behavior of OSF DCE 1.0.2 is to translate synchronous terminating
signals into exceptions. If the exception is not caught, the thread
that caused the exception is terminated. Any thread that goes through
the terminate code causes the entire task to be terminated.
Establish synchronous signal handlers using sigaction()
— It is used to establish handlers for synchronous signals on
an individual thread basis only.
Asynchronous signals — There is no supported mechanism for
establishing signal handlers for asynchronous signals on MPE/iX.
Cancelling threads blocked on a system call — The HP e3000
Kernel Threads provide a cancellation facility that enables one
thread to terminate another. The canceled thread normally terminates
at a well-defined point. Terminating a thread that is blocked while
executing system code is not possible on MPE/iX; only threads
executing non-system code may be canceled.
Using waitpid() — The waitpid() routine
allows the parent thread to specify which child it cares about by
specifying its PID. This call only works for the initial thread;
because children created by any thread within the task are considered
children of the whole task.
Using setjmp and longjmp — Do not use
calls to setjmp and longjmp, these routines save
and restore the signal mask and could inadvertently cause a signal
that another thread is waiting on to be masked. Instead, use
_setjmp and _longjmp; these routines do not
manipulate the signal mask.
When executing _longjmp be aware of the following:
Ensure you are returning to a state saved within the context
of the same thread.
If you _longjmp over a TRY clause, an
exception could try to _longjmp to a stack frame that
no longer exists; and vice versa.
Do not _longjmp out of a signal handler.
|