home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / api.zip / API.INF (.txt) next >
OS/2 Help File  |  1994-04-20  |  13KB  |  280 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Introduction ΓòÉΓòÉΓòÉ
  3.  
  4. Because the C Set/2 and C Set++ runtime libraries must use the operating APIs 
  5. to perForm their work, there is a short list of these APIs that can cause the 
  6. runtime library to behave in unexpected ways. 
  7.  
  8. This document will list the APIs that are known to cause problems, and how they 
  9. can be used safely. 
  10.  
  11.  
  12. ΓòÉΓòÉΓòÉ 2. APIs you should never use ΓòÉΓòÉΓòÉ
  13.  
  14. This section describes OS/2 APIs that can cause severe problems with C/C++ 
  15. applications. 
  16.  
  17.  
  18. ΓòÉΓòÉΓòÉ 2.1. DosKillThread() ΓòÉΓòÉΓòÉ
  19.  
  20. In all cases, this API works by sending an OS/2 exception to the thread being 
  21. killed.  It is usually not desirable to kill a thread at an arbitrary point. 
  22. Think of a thread updating a linked list in a multithreaded program. 
  23.  
  24.  1. It probably owns a semaphore to protect the list, so that only one thread 
  25.     can modify it at a time 
  26.  
  27.  2. It probably breaks the linkages at some point in its processing to add or 
  28.     remove an element from the list. 
  29.  
  30. When the exception occurs, the thread terminates unless the exception is 
  31. somehow deferred or handled.  This may have the following unfortunate 
  32. consequences: 
  33.  
  34.  1. The semaphore is left in the "OWNER DIED" state.  The only way to recover 
  35.     from this is to destroy the semaphore and recreate it.  Messy at best... 
  36.  
  37.  2. The linked list may be left in a broken state. 
  38.  
  39. The problem is compounded by the fact that you, in general, do not know what 
  40. the thread is doing when you kill it.  That means that you often have no idea 
  41. what killing it has damaged, or how to repair it! That's a recipe for disaster! 
  42.  
  43. This API is particularly dangerous if the thread could have been executing code 
  44. over which you have no control (like the C/C++ runtime code, or an OS API). 
  45. You must assume that this code cannot tolerate having its thread of execution 
  46. killed. 
  47.  
  48. The limitations on this API depend on which version of OS/2 you are running. 
  49.  
  50.  
  51. ΓòÉΓòÉΓòÉ 2.1.1. DosKillThread on OS/2 2.0 and 2.1 ΓòÉΓòÉΓòÉ
  52.  
  53. To put it bluntly, never use this API on this operating system.  There are no 
  54. circumstances where this API is safe to use with C Set/2 or C Set++.  The API 
  55. works by sending the synchronous process termination exception 
  56. (XCPT_PROCESS_TERMINATE) to the thread being killed.  There is no way for the 
  57. target thread to defer or ignore the exception.  It must handle it and then 
  58. terminate. 
  59.  
  60. In most cases, protecting a thread so that it can be killed is not possible. 
  61. The problem is essentially the same as writing code that can survive a 
  62. protection violation; a usually impossible task. 
  63.  
  64.  1. If your code makes any calls to any functions that you do not completely 
  65.     control, you must assume that calling DosKillThread() is unsafe.  This 
  66.     includes OS/2 APIs, C/C++ runtime functions (other than inlined functions), 
  67.     database calls, and so on.  This includes C++ constructs that become 
  68.     runtime functions, like new and delete. 
  69.  
  70.  2. Assuming that you can satisfy the first point, you will need to write an 
  71.     OS/2 exception handler to intercept the XCPT_PROCESS_TERMINATE exception, 
  72.     which will then 'throw' a C++ exception.  You will need to 'catch' and 
  73.     "re-throw' the exception at every point in your code that needs to be 
  74.     cleaned up. 
  75.  
  76. Note:  Do not assume that you can test code using this API.  Due to the fact 
  77. that OS/2 uses a pre-emptive multitasking algorithm, the timing of thread swaps 
  78. is, effectively, indeterminate.  This means that test runs are not repeatable, 
  79. and that reliable testing is not possible.  You must "prove" your code correct 
  80. by a formal inspection process. 
  81.  
  82.  
  83. ΓòÉΓòÉΓòÉ 2.1.2. DosKillThread on OS/2 2.11 ΓòÉΓòÉΓòÉ
  84.  
  85. Unlike the situation on OS/2 2.0 and 2.1, on this version of the operating 
  86. system, this API is now merely difficult to use safely.  It cannot be used 
  87. unless the thread being killed has been designed to allow it.  On this version 
  88. of OS/2 the API works by sending the asynchronous process termination exception 
  89. (XCPT_ASYNC_PROCESS_TERMINATE) to the thread being killed.  Unlike the 
  90. synchronous termination exception, this exception can be either deferred or 
  91. ignored. 
  92.  
  93. The C Set/2 and C Set++ runtime libraries protect themselves against this 
  94. problem by deferring the exception until the runtime library call has returned 
  95. to user code.  This has one side effect:  you cannot kill a thread that is 
  96. waiting on keyboard input (sorry about that, but not doing so causes some 
  97. really nasty intermittent problems with the runtime library). 
  98.  
  99. You can protect your own code in three ways: 
  100.  
  101.  1. You can put your code into a "must complete" section, by using the 
  102.     DosEnterMustComplete() and DosExitMustComplete() APIs.  See the cautions 
  103.     regarding them in this document.  The thread terminates after you exit the 
  104.     topmost must complete section. 
  105.  
  106.  2. You can write an OS/2 exception handler to simply ignore the exception.  A 
  107.     bit drastic! 
  108.  
  109.  3. You can write an OS/2 exception handler to catch the exception, put a "mark 
  110.     on the wall", and then ignore the exception.  At an appropriate point in 
  111.     your code, you check for the "mark on the wall", and if it's there, 
  112.     terminate the thread. 
  113.  
  114. Of the three, the last has the best performance, and the first is the easiest. 
  115.  
  116. Note:  Do not assume that you can test code using this API.  Due to the fact 
  117. that OS/2 uses a pre-emptive multitasking algorithm, the timing of thread swaps 
  118. is, effectively, indeterminate.  This means that test runs are not repeatable, 
  119. and that reliable testing is not possible.  You must "prove" your code correct 
  120. by a formal inspection process. 
  121.  
  122.  
  123. ΓòÉΓòÉΓòÉ 2.2. DosUnwindException() ΓòÉΓòÉΓòÉ
  124.  
  125. This API can remove the C and C++ OS/2 exception handlers from the stack, 
  126. causing C signal handlers or C++ exception handling to malfunction. It also 
  127. requires knowledge of the machine state, which is not available in either of 
  128. these languages. 
  129.  
  130. You are recommended to use longjmp() instead.  longjmp() will unwind OS/2 
  131. exception handlers from the stack, preventing any problems with them. 
  132.  
  133.  
  134. ΓòÉΓòÉΓòÉ 2.3. DosAcknowledgeSignalException() ΓòÉΓòÉΓòÉ
  135.  
  136. Use of this function is recommended only from within a user written OS/2 
  137. exception handler.  It is not required unless you wish to unblock the OS/2 
  138. signal exceptions without leaving an OS/2 exception handler. OS/2 Signal 
  139. exceptions are automatically acknowledged if the OS/2 exception handler returns 
  140. XCPT_CONTINUE_EXECUTION. 
  141.  
  142. Using this API inside a C signal handler may cause the C/C++ handling of OS/2 
  143. signal exceptions to fail, as this depends on the library controlling when OS/2 
  144. signal exceptions are acknowledged.. The library OS/2 exception handler will 
  145. take care of acknowledging signals for you. 
  146.  
  147.  
  148. ΓòÉΓòÉΓòÉ 3. APIs that may be used with caution ΓòÉΓòÉΓòÉ
  149.  
  150. This section describes OS/2 APIs that can be used in C/C++ applications as long 
  151. as appropriate precautions are taken. 
  152.  
  153.  
  154. ΓòÉΓòÉΓòÉ 3.1. DosSuspendThread() ΓòÉΓòÉΓòÉ
  155.  
  156. This API can cause a thread to stop at an arbitrary point.  Since, in most 
  157. useful multithreaded programs, a suspended thread is likely to own a mutex 
  158. semaphore, you are exposed to a deadlock.  The only safe way to use this API is 
  159. to call DosResumeThread() as soon as possible, and to avoid making any calls to 
  160. any C/C++ runtime routine while a thread is suspended.  This API is of limited 
  161. use, and can often be replaced with an OS/2 semaphore. 
  162.  
  163.  
  164. ΓòÉΓòÉΓòÉ 3.2. DosEnterCritSec(): ΓòÉΓòÉΓòÉ
  165.  
  166. This API prevents thread switching within your process.  It is equivalent to 
  167. calling DosSuspendThread() for every thread in your process except the current 
  168. thread.  For each call to DosEnterCritSec(), you must call DosExitCritSec(). 
  169. Keep critical sections short, and do not put calls to OS/2 APIs or C/C++ 
  170. library routines inside them. 
  171.  
  172. Where possible (and it usually is), use an OS/2  mutex semaphore rather than 
  173. this API. 
  174.  
  175.  
  176. ΓòÉΓòÉΓòÉ 3.3. DosExit() ΓòÉΓòÉΓòÉ
  177.  
  178. Unless you are using the subsystems programming library (the /Rn compile 
  179. option), this API is not supported in conjunction with C Set++ applications. 
  180.  
  181. DosExit prevents the runtime library from cleaning up, and inhibits running the 
  182. atexit() and onexit() routines.  If used in place of _endthread(), it can cause 
  183. a subsequently started thread to start up with invalid default values (see 
  184. DosCreateThread()). 
  185.  
  186.  Use exit(), abort(), _endthread(), or fall out the bottom of main(). These do 
  187. much the same thing, and they're portable too! 
  188.  
  189.  
  190. ΓòÉΓòÉΓòÉ 3.4. DosSetSignalExceptionFocus() ΓòÉΓòÉΓòÉ
  191.  
  192. This API is fully supported under the susbsystems programming library (the /Rn 
  193. compile option). 
  194.  
  195. With the single and multitasking libraries, you are exposed to changing the 
  196. behavious of the C signal handling behaviour.  C++ applications assume that 
  197. they have the focus for signal exceptions.  Removing the focus will prevent you 
  198. from getting SIGINT and SIGBREAK signals from the keyboard.  This is not a 
  199. problem is you do not intercept these signals. 
  200.  
  201. DosCreateThread() 
  202.  
  203. This API is the only way to start a new thread if you are using the subsystems 
  204. programming libraries (compile option /Rn), and its use is supported under that 
  205. set of circumstances. 
  206.  
  207. This API is not supported for use with the singly threaded libraries (compile 
  208. option /Gm-), as these libraries lack the internal controls to allow multiple 
  209. threads to use the library. 
  210.  
  211. DosCreateThread() is supported for use with the multithreaded libraries 
  212. (compile option /Gm+) as long as the following code is also used: 
  213.  
  214.  1. The function in the new thread must register the C/C++ OS/2 exception 
  215.     handler. 
  216.  
  217.  2. The new thread must call _fpreset() before doing any floating point 
  218.     operations 
  219.  
  220.  3. The new thread must never end by falling out of the bottom of the function. 
  221.     It must call _endthread(). 
  222.  
  223. An example of this would be: 
  224.  
  225.      /* register the C/C++ exception handler */
  226.      #pragma handler(threadfn)
  227.      void threadfn(ULONG arg) {
  228.         _fpreset();   /* reset the 80386 exception handler */
  229.         .
  230.         .
  231.         .
  232.         _endthread();  /* exit with _endthread() so the library */
  233.                        /* data areas are cleaned up */
  234.      }
  235.  
  236.  
  237. ΓòÉΓòÉΓòÉ 3.5. DosEnterMustComplete(): ΓòÉΓòÉΓòÉ
  238.  
  239. This API is used to hold off all asynchronous exceptions, including 
  240. XCPT_ASYNC_PROCESS_TERMINATE.  You must call DosExitMustComplete() to reenable 
  241. asynchronous exceptions.  Since terminating a multithreaded process causes an 
  242. asynchrnous process termination exception (XCPT_ASYNC_PROCESS_TERMINATE) on 
  243. each thread, multithreaded processes cannot end if any thread is in a must 
  244. complete section. 
  245.  
  246.  
  247. ΓòÉΓòÉΓòÉ 3.6. DosSetExceptionHandler() ΓòÉΓòÉΓòÉ
  248.  
  249. This API is supported for use with the subsystems programming library, although 
  250. it is assumed that you understand how OS/2 exceptions work. 
  251.  
  252. When used with the standard libraries (single or multithreaded), this API will 
  253. override the runtime library excpetion handling.  You should handle only those 
  254. exception you specifically expect, and pass all others on. If you intercept the 
  255. OS/2 exceptions, you may inhibit the calling of previosly registered signal 
  256. handlers.  See the companion EXCEPT.INF file for a full treatment of the 
  257. subject. 
  258.  
  259.  
  260. ΓòÉΓòÉΓòÉ 3.7. DosScanEnv() ΓòÉΓòÉΓòÉ
  261.  
  262. This API is supported for use with the subsystems programming library as the 
  263. only way to get the OS/2 environment data. 
  264.  
  265. Its behaviour with the standard libraries (single or multithreaded), is not 
  266. exactly the same as the getenv() library function.  The DosScanEnv() API will 
  267. give you values that were in the environment when the process started.  The 
  268. getenv() library function will give you those values, as modified by any 
  269. intervening _putenv() calls. 
  270.  
  271.  
  272. ΓòÉΓòÉΓòÉ 3.8. OS/2 File I/O APIs ΓòÉΓòÉΓòÉ
  273.  
  274. These APIs are equivalent to the low level I/O functions in IO.H.  They may be 
  275. freely intermixed with those calls, as the low level I/O handles are also OS/2 
  276. file handles. 
  277.  
  278. Intermixing C/C++ stream I/O with either OS/2 File I/O APIs or the C/C++ low 
  279. level I/O functions should be avoided.  Use either one or the other on any 
  280. file, as both have the implicit assumption that they "own the file".