|  |  | 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. 
 
 |