passenger 2.2.11 → 2.2.12

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (287) hide show
  1. data/NEWS +29 -0
  2. data/bin/passenger-install-nginx-module +1 -1
  3. data/doc/Users guide Apache.html +38 -7
  4. data/doc/Users guide Nginx.html +36 -5
  5. data/doc/cxxapi/AbstractSpawnManager_8h-source.html +1 -1
  6. data/doc/cxxapi/Account_8h-source.html +1 -1
  7. data/doc/cxxapi/AccountsDatabase_8h-source.html +1 -1
  8. data/doc/cxxapi/AgentsStarter_8h-source.html +1 -1
  9. data/doc/cxxapi/BCrypt_8h-source.html +1 -1
  10. data/doc/cxxapi/Blowfish_8h-source.html +1 -1
  11. data/doc/cxxapi/Bucket_8h-source.html +5 -4
  12. data/doc/cxxapi/Constants_8h-source.html +2 -2
  13. data/doc/cxxapi/ContentHandler_8h-source.html +1 -1
  14. data/doc/cxxapi/DirectoryMapper_8h-source.html +10 -9
  15. data/doc/cxxapi/EventedServer_8h-source.html +415 -0
  16. data/doc/cxxapi/Exceptions_8h-source.html +1 -1
  17. data/doc/cxxapi/FileDescriptor_8h-source.html +1 -1
  18. data/doc/cxxapi/Hooks_8h-source.html +3 -2
  19. data/doc/cxxapi/HttpStatusExtractor_8h-source.html +324 -323
  20. data/doc/cxxapi/Logging_8h-source.html +643 -546
  21. data/doc/cxxapi/MessageChannel_8h-source.html +429 -404
  22. data/doc/cxxapi/MessageClient_8h-source.html +1 -1
  23. data/doc/cxxapi/MessageReadersWriters_8h-source.html +451 -0
  24. data/doc/cxxapi/MessageServer_8h-source.html +1 -1
  25. data/doc/cxxapi/PoolOptions_8h-source.html +287 -279
  26. data/doc/cxxapi/Process_8h-source.html +178 -167
  27. data/doc/cxxapi/RandomGenerator_8h-source.html +45 -18
  28. data/doc/cxxapi/ResourceLocator_8h-source.html +3 -3
  29. data/doc/cxxapi/ScgiRequestParser_8h-source.html +344 -343
  30. data/doc/cxxapi/ServerInstanceDir_8h-source.html +1 -1
  31. data/doc/cxxapi/Session_8h-source.html +387 -374
  32. data/doc/cxxapi/SpawnManager_8h-source.html +547 -538
  33. data/doc/cxxapi/StaticContentHandler_8h-source.html +1 -1
  34. data/doc/cxxapi/StaticString_8h-source.html +1 -1
  35. data/doc/cxxapi/StringListCreator_8h-source.html +1 -1
  36. data/doc/cxxapi/Utils_8h-source.html +545 -520
  37. data/doc/cxxapi/annotated.html +11 -8
  38. data/doc/cxxapi/apache2_2Configuration_8h-source.html +1 -1
  39. data/doc/cxxapi/classAgentWatcher-members.html +1 -1
  40. data/doc/cxxapi/classAgentWatcher.html +1 -1
  41. data/doc/cxxapi/classClient-members.html +1 -1
  42. data/doc/cxxapi/classClient.html +1 -1
  43. data/doc/cxxapi/classHooks-members.html +16 -13
  44. data/doc/cxxapi/classHooks.html +69 -73
  45. data/doc/cxxapi/classPassenger_1_1AbstractSpawnManager-members.html +1 -1
  46. data/doc/cxxapi/classPassenger_1_1AbstractSpawnManager.html +1 -1
  47. data/doc/cxxapi/classPassenger_1_1ArgumentException-members.html +1 -1
  48. data/doc/cxxapi/classPassenger_1_1ArgumentException.html +1 -1
  49. data/doc/cxxapi/classPassenger_1_1ArrayReader-members.html +33 -0
  50. data/doc/cxxapi/classPassenger_1_1ArrayReader.html +47 -0
  51. data/doc/cxxapi/classPassenger_1_1BufferedUpload-members.html +1 -1
  52. data/doc/cxxapi/classPassenger_1_1BufferedUpload.html +1 -1
  53. data/doc/cxxapi/classPassenger_1_1BusyException-members.html +1 -1
  54. data/doc/cxxapi/classPassenger_1_1BusyException.html +1 -1
  55. data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +1 -1
  56. data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +1 -1
  57. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +18 -15
  58. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +89 -99
  59. data/doc/cxxapi/classPassenger_1_1EOFException-members.html +1 -1
  60. data/doc/cxxapi/classPassenger_1_1EOFException.html +1 -1
  61. data/doc/cxxapi/classPassenger_1_1EventFd-members.html +1 -1
  62. data/doc/cxxapi/classPassenger_1_1EventFd.html +1 -1
  63. data/doc/cxxapi/classPassenger_1_1FileDescriptor-members.html +1 -1
  64. data/doc/cxxapi/classPassenger_1_1FileDescriptor.html +1 -1
  65. data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +1 -1
  66. data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +1 -1
  67. data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +1 -1
  68. data/doc/cxxapi/classPassenger_1_1FileSystemException.html +1 -1
  69. data/doc/cxxapi/classPassenger_1_1HttpStatusExtractor-members.html +1 -1
  70. data/doc/cxxapi/classPassenger_1_1HttpStatusExtractor.html +2 -2
  71. data/doc/cxxapi/classPassenger_1_1IOException-members.html +1 -1
  72. data/doc/cxxapi/classPassenger_1_1IOException.html +1 -1
  73. data/doc/cxxapi/classPassenger_1_1MemZeroGuard-members.html +1 -1
  74. data/doc/cxxapi/classPassenger_1_1MemZeroGuard.html +1 -1
  75. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +1 -1
  76. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +1 -1
  77. data/doc/cxxapi/classPassenger_1_1MessageServer-members.html +1 -1
  78. data/doc/cxxapi/classPassenger_1_1MessageServer.html +1 -1
  79. data/doc/cxxapi/classPassenger_1_1MessageServer_1_1ClientContext-members.html +1 -1
  80. data/doc/cxxapi/classPassenger_1_1MessageServer_1_1ClientContext.html +1 -1
  81. data/doc/cxxapi/classPassenger_1_1MessageServer_1_1CommonClientContext-members.html +1 -1
  82. data/doc/cxxapi/classPassenger_1_1MessageServer_1_1CommonClientContext.html +1 -1
  83. data/doc/cxxapi/classPassenger_1_1MessageServer_1_1Handler-members.html +1 -1
  84. data/doc/cxxapi/classPassenger_1_1MessageServer_1_1Handler.html +1 -1
  85. data/doc/cxxapi/classPassenger_1_1Process-members.html +4 -3
  86. data/doc/cxxapi/classPassenger_1_1Process.html +40 -9
  87. data/doc/cxxapi/classPassenger_1_1RandomGenerator-members.html +2 -1
  88. data/doc/cxxapi/classPassenger_1_1RandomGenerator.html +29 -2
  89. data/doc/cxxapi/classPassenger_1_1RuntimeException-members.html +1 -1
  90. data/doc/cxxapi/classPassenger_1_1RuntimeException.html +1 -1
  91. data/doc/cxxapi/classPassenger_1_1ScalarReader-members.html +33 -0
  92. data/doc/cxxapi/classPassenger_1_1ScalarReader.html +47 -0
  93. data/doc/cxxapi/classPassenger_1_1ScgiRequestParser-members.html +1 -1
  94. data/doc/cxxapi/classPassenger_1_1ScgiRequestParser.html +1 -1
  95. data/doc/cxxapi/classPassenger_1_1SecurityException-members.html +1 -1
  96. data/doc/cxxapi/classPassenger_1_1SecurityException.html +1 -1
  97. data/doc/cxxapi/classPassenger_1_1Session-members.html +1 -1
  98. data/doc/cxxapi/classPassenger_1_1Session.html +2 -2
  99. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +1 -1
  100. data/doc/cxxapi/classPassenger_1_1SpawnException.html +1 -1
  101. data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +2 -2
  102. data/doc/cxxapi/classPassenger_1_1SpawnManager.html +6 -18
  103. data/doc/cxxapi/classPassenger_1_1StandardSession-members.html +1 -1
  104. data/doc/cxxapi/classPassenger_1_1StandardSession.html +1 -1
  105. data/doc/cxxapi/classPassenger_1_1StaticString-members.html +1 -1
  106. data/doc/cxxapi/classPassenger_1_1StaticString.html +1 -1
  107. data/doc/cxxapi/classPassenger_1_1SystemException-members.html +1 -1
  108. data/doc/cxxapi/classPassenger_1_1SystemException.html +1 -1
  109. data/doc/cxxapi/classPassenger_1_1TimeRetrievalException-members.html +1 -1
  110. data/doc/cxxapi/classPassenger_1_1TimeRetrievalException.html +1 -1
  111. data/doc/cxxapi/classPassenger_1_1TimeoutException-members.html +1 -1
  112. data/doc/cxxapi/classPassenger_1_1TimeoutException.html +1 -1
  113. data/doc/cxxapi/classPassenger_1_1Uint16Reader-members.html +33 -0
  114. data/doc/cxxapi/classPassenger_1_1Uint16Reader.html +47 -0
  115. data/doc/cxxapi/classPassenger_1_1Uint32Reader-members.html +33 -0
  116. data/doc/cxxapi/classPassenger_1_1Uint32Reader.html +47 -0
  117. data/doc/cxxapi/classServer-members.html +1 -1
  118. data/doc/cxxapi/classServer.html +1 -1
  119. data/doc/cxxapi/classServerInstanceDirToucher-members.html +1 -1
  120. data/doc/cxxapi/classServerInstanceDirToucher.html +1 -1
  121. data/doc/cxxapi/classes.html +13 -10
  122. data/doc/cxxapi/definitions_8h-source.html +2 -1
  123. data/doc/cxxapi/doxygen.css +91 -0
  124. data/doc/cxxapi/files.html +16 -13
  125. data/doc/cxxapi/functions.html +32 -21
  126. data/doc/cxxapi/functions_enum.html +1 -1
  127. data/doc/cxxapi/functions_eval.html +1 -1
  128. data/doc/cxxapi/functions_func.html +32 -21
  129. data/doc/cxxapi/functions_vars.html +3 -1
  130. data/doc/cxxapi/graph_legend.html +20 -15
  131. data/doc/cxxapi/graph_legend.png +0 -0
  132. data/doc/cxxapi/group__Configuration.html +51 -64
  133. data/doc/cxxapi/group__Configuration.png +0 -0
  134. data/doc/cxxapi/group__Core.html +24 -26
  135. data/doc/cxxapi/group__Core.png +0 -0
  136. data/doc/cxxapi/group__Exceptions.html +1 -1
  137. data/doc/cxxapi/group__Hooks.html +17 -15
  138. data/doc/cxxapi/group__Hooks.png +0 -0
  139. data/doc/cxxapi/group__Support.html +11 -9
  140. data/doc/cxxapi/hierarchy.html +6 -1
  141. data/doc/cxxapi/index.html +10 -5
  142. data/doc/cxxapi/inherit__graph__10.map +1 -1
  143. data/doc/cxxapi/inherit__graph__10.md5 +1 -1
  144. data/doc/cxxapi/inherit__graph__10.png +0 -0
  145. data/doc/cxxapi/inherit__graph__11.map +1 -1
  146. data/doc/cxxapi/inherit__graph__11.md5 +1 -1
  147. data/doc/cxxapi/inherit__graph__11.png +0 -0
  148. data/doc/cxxapi/inherit__graph__12.map +1 -1
  149. data/doc/cxxapi/inherit__graph__12.md5 +1 -1
  150. data/doc/cxxapi/inherit__graph__12.png +0 -0
  151. data/doc/cxxapi/inherit__graph__13.map +1 -1
  152. data/doc/cxxapi/inherit__graph__13.md5 +1 -1
  153. data/doc/cxxapi/inherit__graph__13.png +0 -0
  154. data/doc/cxxapi/inherit__graph__14.map +1 -3
  155. data/doc/cxxapi/inherit__graph__14.md5 +1 -1
  156. data/doc/cxxapi/inherit__graph__14.png +0 -0
  157. data/doc/cxxapi/inherit__graph__15.map +1 -1
  158. data/doc/cxxapi/inherit__graph__15.md5 +1 -1
  159. data/doc/cxxapi/inherit__graph__15.png +0 -0
  160. data/doc/cxxapi/inherit__graph__16.map +3 -1
  161. data/doc/cxxapi/inherit__graph__16.md5 +1 -1
  162. data/doc/cxxapi/inherit__graph__16.png +0 -0
  163. data/doc/cxxapi/inherit__graph__17.map +1 -1
  164. data/doc/cxxapi/inherit__graph__17.md5 +1 -1
  165. data/doc/cxxapi/inherit__graph__17.png +0 -0
  166. data/doc/cxxapi/inherit__graph__18.map +1 -2
  167. data/doc/cxxapi/inherit__graph__18.md5 +1 -1
  168. data/doc/cxxapi/inherit__graph__18.png +0 -0
  169. data/doc/cxxapi/inherit__graph__19.map +1 -1
  170. data/doc/cxxapi/inherit__graph__19.md5 +1 -1
  171. data/doc/cxxapi/inherit__graph__19.png +0 -0
  172. data/doc/cxxapi/inherit__graph__20.map +2 -1
  173. data/doc/cxxapi/inherit__graph__20.md5 +1 -1
  174. data/doc/cxxapi/inherit__graph__20.png +0 -0
  175. data/doc/cxxapi/inherit__graph__21.map +1 -1
  176. data/doc/cxxapi/inherit__graph__21.md5 +1 -1
  177. data/doc/cxxapi/inherit__graph__21.png +0 -0
  178. data/doc/cxxapi/inherit__graph__22.map +1 -1
  179. data/doc/cxxapi/inherit__graph__22.md5 +1 -1
  180. data/doc/cxxapi/inherit__graph__22.png +0 -0
  181. data/doc/cxxapi/inherit__graph__23.map +1 -1
  182. data/doc/cxxapi/inherit__graph__23.md5 +1 -1
  183. data/doc/cxxapi/inherit__graph__23.png +0 -0
  184. data/doc/cxxapi/inherit__graph__24.map +1 -1
  185. data/doc/cxxapi/inherit__graph__24.md5 +1 -1
  186. data/doc/cxxapi/inherit__graph__24.png +0 -0
  187. data/doc/cxxapi/inherit__graph__25.map +1 -1
  188. data/doc/cxxapi/inherit__graph__25.md5 +1 -1
  189. data/doc/cxxapi/inherit__graph__25.png +0 -0
  190. data/doc/cxxapi/inherit__graph__26.map +1 -1
  191. data/doc/cxxapi/inherit__graph__26.md5 +1 -1
  192. data/doc/cxxapi/inherit__graph__26.png +0 -0
  193. data/doc/cxxapi/inherit__graph__27.map +1 -2
  194. data/doc/cxxapi/inherit__graph__27.md5 +1 -1
  195. data/doc/cxxapi/inherit__graph__27.png +0 -0
  196. data/doc/cxxapi/inherit__graph__28.map +1 -1
  197. data/doc/cxxapi/inherit__graph__28.md5 +1 -1
  198. data/doc/cxxapi/inherit__graph__28.png +0 -0
  199. data/doc/cxxapi/inherit__graph__29.map +1 -1
  200. data/doc/cxxapi/inherit__graph__29.md5 +1 -1
  201. data/doc/cxxapi/inherit__graph__29.png +0 -0
  202. data/doc/cxxapi/inherit__graph__30.map +2 -1
  203. data/doc/cxxapi/inherit__graph__30.md5 +1 -1
  204. data/doc/cxxapi/inherit__graph__30.png +0 -0
  205. data/doc/cxxapi/inherit__graph__31.map +1 -3
  206. data/doc/cxxapi/inherit__graph__31.md5 +1 -1
  207. data/doc/cxxapi/inherit__graph__31.png +0 -0
  208. data/doc/cxxapi/inherit__graph__32.map +1 -1
  209. data/doc/cxxapi/inherit__graph__32.md5 +1 -1
  210. data/doc/cxxapi/inherit__graph__32.png +0 -0
  211. data/doc/cxxapi/inherit__graph__33.map +1 -1
  212. data/doc/cxxapi/inherit__graph__33.md5 +1 -1
  213. data/doc/cxxapi/inherit__graph__33.png +0 -0
  214. data/doc/cxxapi/inherit__graph__34.map +3 -1
  215. data/doc/cxxapi/inherit__graph__34.md5 +1 -1
  216. data/doc/cxxapi/inherit__graph__34.png +0 -0
  217. data/doc/cxxapi/inherit__graph__35.map +1 -1
  218. data/doc/cxxapi/inherit__graph__35.md5 +1 -1
  219. data/doc/cxxapi/inherit__graph__35.png +0 -0
  220. data/doc/cxxapi/inherit__graph__36.map +1 -1
  221. data/doc/cxxapi/inherit__graph__36.md5 +1 -1
  222. data/doc/cxxapi/inherit__graph__36.png +0 -0
  223. data/doc/cxxapi/inherit__graph__37.map +1 -0
  224. data/doc/cxxapi/inherit__graph__37.md5 +1 -0
  225. data/doc/cxxapi/inherit__graph__37.png +0 -0
  226. data/doc/cxxapi/inherit__graph__38.map +1 -0
  227. data/doc/cxxapi/inherit__graph__38.md5 +1 -0
  228. data/doc/cxxapi/inherit__graph__38.png +0 -0
  229. data/doc/cxxapi/inherit__graph__39.map +1 -0
  230. data/doc/cxxapi/inherit__graph__39.md5 +1 -0
  231. data/doc/cxxapi/inherit__graph__39.png +0 -0
  232. data/doc/cxxapi/inherit__graph__5.map +1 -1
  233. data/doc/cxxapi/inherit__graph__5.md5 +1 -1
  234. data/doc/cxxapi/inherit__graph__5.png +0 -0
  235. data/doc/cxxapi/inherit__graph__6.map +1 -1
  236. data/doc/cxxapi/inherit__graph__6.md5 +1 -1
  237. data/doc/cxxapi/inherit__graph__6.png +0 -0
  238. data/doc/cxxapi/inherit__graph__7.map +1 -1
  239. data/doc/cxxapi/inherit__graph__7.md5 +1 -1
  240. data/doc/cxxapi/inherit__graph__7.png +0 -0
  241. data/doc/cxxapi/inherit__graph__8.map +1 -1
  242. data/doc/cxxapi/inherit__graph__8.md5 +1 -1
  243. data/doc/cxxapi/inherit__graph__8.png +0 -0
  244. data/doc/cxxapi/inherit__graph__9.map +1 -1
  245. data/doc/cxxapi/inherit__graph__9.md5 +1 -1
  246. data/doc/cxxapi/inherit__graph__9.png +0 -0
  247. data/doc/cxxapi/inherits.html +46 -31
  248. data/doc/cxxapi/main.html +12 -11
  249. data/doc/cxxapi/modules.html +16 -13
  250. data/doc/cxxapi/namespacePassenger.html +82 -5
  251. data/doc/cxxapi/namespacemembers.html +5 -3
  252. data/doc/cxxapi/namespacemembers_enum.html +1 -1
  253. data/doc/cxxapi/namespacemembers_eval.html +1 -1
  254. data/doc/cxxapi/namespacemembers_func.html +5 -3
  255. data/doc/cxxapi/namespacemembers_type.html +1 -1
  256. data/doc/cxxapi/namespaces.html +2 -2
  257. data/doc/cxxapi/nginx_2Configuration_8h-source.html +43 -42
  258. data/doc/cxxapi/ngx__http__passenger__module_8h-source.html +1 -1
  259. data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +1 -1
  260. data/doc/cxxapi/structPassenger_1_1AnythingToString.html +1 -1
  261. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01StaticString_01_4_01_4-members.html +33 -0
  262. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01StaticString_01_4_01_4.html +52 -0
  263. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +1 -1
  264. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +1 -1
  265. data/doc/cxxapi/structPassenger_1_1MessageServer_1_1DisconnectEventBroadcastGuard-members.html +1 -1
  266. data/doc/cxxapi/structPassenger_1_1MessageServer_1_1DisconnectEventBroadcastGuard.html +1 -1
  267. data/doc/cxxapi/structPassenger_1_1PoolOptions-members.html +3 -2
  268. data/doc/cxxapi/structPassenger_1_1PoolOptions.html +25 -5
  269. data/doc/cxxapi/structPassenger_1_1StaticString_1_1Hash-members.html +1 -1
  270. data/doc/cxxapi/structPassenger_1_1StaticString_1_1Hash.html +1 -1
  271. data/doc/cxxapi/tabs.css +1 -1
  272. data/doc/cxxapi/tree.html +20 -17
  273. data/doc/users_guide_snippets/tips.txt +28 -0
  274. data/ext/apache2/Hooks.cpp +19 -2
  275. data/ext/common/Utils.cpp +15 -4
  276. data/ext/common/Version.h +1 -1
  277. data/ext/nginx/StaticContentHandler.c +6 -3
  278. data/ext/phusion_passenger/native_support.c +25 -0
  279. data/lib/phusion_passenger/abstract_request_handler.rb +1 -0
  280. data/lib/phusion_passenger/constants.rb +1 -1
  281. data/lib/phusion_passenger/events.rb +3 -0
  282. data/lib/phusion_passenger/platform_info.rb +2 -1
  283. data/lib/phusion_passenger/rack/application_spawner.rb +2 -0
  284. data/lib/phusion_passenger/railz/application_spawner.rb +8 -0
  285. data/lib/phusion_passenger/utils.rb +69 -9
  286. data/lib/phusion_passenger/utils/rewindable_input.rb +10 -6
  287. metadata +55 -17
@@ -415,412 +415,437 @@
415
415
  <a name="l00393"></a>00393 <span class="comment"> * @see readFileDescriptor()</span>
416
416
  <a name="l00394"></a>00394 <span class="comment"> */</span>
417
417
  <a name="l00395"></a><a class="code" href="classPassenger_1_1MessageChannel.html#e0c558e07dcc91900016773b2bec38d8">00395</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1MessageChannel.html#e0c558e07dcc91900016773b2bec38d8" title="Pass a file descriptor.">writeFileDescriptor</a>(<span class="keywordtype">int</span> fileDescriptor, <span class="keywordtype">bool</span> negotiate = <span class="keyword">true</span>) {
418
- <a name="l00396"></a>00396 <span class="keywordflow">if</span> (negotiate) {
419
- <a name="l00397"></a>00397 vector&lt;string&gt; args;
420
- <a name="l00398"></a>00398
421
- <a name="l00399"></a>00399 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args)) {
422
- <a name="l00400"></a>00400 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"Unexpected end of stream encountered"</span>);
423
- <a name="l00401"></a>00401 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (args.size() != 1 || args[0] != <span class="stringliteral">"pass IO"</span>) {
424
- <a name="l00402"></a>00402 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"FD passing negotiation message expected."</span>);
425
- <a name="l00403"></a>00403 }
426
- <a name="l00404"></a>00404 }
427
- <a name="l00405"></a>00405
428
- <a name="l00406"></a>00406 <span class="keyword">struct </span>msghdr msg;
429
- <a name="l00407"></a>00407 <span class="keyword">struct </span>iovec vec;
430
- <a name="l00408"></a>00408 <span class="keywordtype">char</span> dummy[1];
431
- <a name="l00409"></a>00409 <span class="preprocessor"> #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)</span>
432
- <a name="l00410"></a>00410 <span class="preprocessor"></span> <span class="keyword">struct </span>{
433
- <a name="l00411"></a>00411 <span class="keyword">struct </span>cmsghdr header;
434
- <a name="l00412"></a>00412 <span class="keywordtype">int</span> fd;
435
- <a name="l00413"></a>00413 } control_data;
436
- <a name="l00414"></a>00414 <span class="preprocessor"> #else</span>
437
- <a name="l00415"></a>00415 <span class="preprocessor"></span> <span class="keywordtype">char</span> control_data[CMSG_SPACE(<span class="keyword">sizeof</span>(<span class="keywordtype">int</span>))];
438
- <a name="l00416"></a>00416 <span class="preprocessor"> #endif</span>
439
- <a name="l00417"></a>00417 <span class="preprocessor"></span> <span class="keyword">struct </span>cmsghdr *control_header;
440
- <a name="l00418"></a>00418 <span class="keywordtype">int</span> ret;
441
- <a name="l00419"></a>00419
442
- <a name="l00420"></a>00420 msg.msg_name = NULL;
443
- <a name="l00421"></a>00421 msg.msg_namelen = 0;
444
- <a name="l00422"></a>00422
445
- <a name="l00423"></a>00423 <span class="comment">/* Linux and Solaris require msg_iov to be non-NULL. */</span>
446
- <a name="l00424"></a>00424 dummy[0] = <span class="charliteral">'\0'</span>;
447
- <a name="l00425"></a>00425 vec.iov_base = dummy;
448
- <a name="l00426"></a>00426 vec.iov_len = <span class="keyword">sizeof</span>(dummy);
449
- <a name="l00427"></a>00427 msg.msg_iov = &amp;vec;
450
- <a name="l00428"></a>00428 msg.msg_iovlen = 1;
451
- <a name="l00429"></a>00429
452
- <a name="l00430"></a>00430 msg.msg_control = (caddr_t) &amp;control_data;
453
- <a name="l00431"></a>00431 msg.msg_controllen = <span class="keyword">sizeof</span>(control_data);
454
- <a name="l00432"></a>00432 msg.msg_flags = 0;
455
- <a name="l00433"></a>00433
456
- <a name="l00434"></a>00434 control_header = CMSG_FIRSTHDR(&amp;msg);
457
- <a name="l00435"></a>00435 control_header-&gt;cmsg_level = SOL_SOCKET;
458
- <a name="l00436"></a>00436 control_header-&gt;cmsg_type = SCM_RIGHTS;
459
- <a name="l00437"></a>00437 <span class="preprocessor"> #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)</span>
460
- <a name="l00438"></a>00438 <span class="preprocessor"></span> control_header-&gt;cmsg_len = <span class="keyword">sizeof</span>(control_data);
461
- <a name="l00439"></a>00439 control_data.fd = fileDescriptor;
462
- <a name="l00440"></a>00440 <span class="preprocessor"> #else</span>
463
- <a name="l00441"></a>00441 <span class="preprocessor"></span> control_header-&gt;cmsg_len = CMSG_LEN(<span class="keyword">sizeof</span>(<span class="keywordtype">int</span>));
464
- <a name="l00442"></a>00442 memcpy(CMSG_DATA(control_header), &amp;fileDescriptor, <span class="keyword">sizeof</span>(<span class="keywordtype">int</span>));
465
- <a name="l00443"></a>00443 <span class="preprocessor"> #endif</span>
466
- <a name="l00444"></a>00444 <span class="preprocessor"></span>
467
- <a name="l00445"></a>00445 ret = syscalls::sendmsg(fd, &amp;msg, 0);
468
- <a name="l00446"></a>00446 <span class="keywordflow">if</span> (ret == -1) {
469
- <a name="l00447"></a>00447 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot send file descriptor with sendmsg()"</span>, errno);
470
- <a name="l00448"></a>00448 }
471
- <a name="l00449"></a>00449 }
472
- <a name="l00450"></a>00450 <span class="comment"></span>
473
- <a name="l00451"></a>00451 <span class="comment"> /**</span>
474
- <a name="l00452"></a>00452 <span class="comment"> * Read an array message from the underlying file descriptor.</span>
475
- <a name="l00453"></a>00453 <span class="comment"> *</span>
476
- <a name="l00454"></a>00454 <span class="comment"> * @param args The message will be put in this variable.</span>
477
- <a name="l00455"></a>00455 <span class="comment"> * @return Whether end-of-file has been reached. If so, then the contents</span>
478
- <a name="l00456"></a>00456 <span class="comment"> * of &lt;tt&gt;args&lt;/tt&gt; will be undefined.</span>
479
- <a name="l00457"></a>00457 <span class="comment"> * @throws SystemException If an error occured while receiving the message.</span>
480
- <a name="l00458"></a>00458 <span class="comment"> * @throws boost::thread_interrupted</span>
481
- <a name="l00459"></a>00459 <span class="comment"> * @see write()</span>
482
- <a name="l00460"></a>00460 <span class="comment"> */</span>
483
- <a name="l00461"></a><a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e">00461</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(vector&lt;string&gt; &amp;args) {
484
- <a name="l00462"></a>00462 uint16_t size;
485
- <a name="l00463"></a>00463 <span class="keywordtype">int</span> ret;
486
- <a name="l00464"></a>00464 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> alreadyRead = 0;
487
- <a name="l00465"></a>00465
488
- <a name="l00466"></a>00466 <span class="keywordflow">do</span> {
489
- <a name="l00467"></a>00467 ret = <a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">syscalls::read</a>(fd, (<span class="keywordtype">char</span> *) &amp;size + alreadyRead, <span class="keyword">sizeof</span>(size) - alreadyRead);
490
- <a name="l00468"></a>00468 <span class="keywordflow">if</span> (ret == -1) {
491
- <a name="l00469"></a>00469 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"read() failed"</span>, errno);
492
- <a name="l00470"></a>00470 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (ret == 0) {
493
- <a name="l00471"></a>00471 <span class="keywordflow">return</span> <span class="keyword">false</span>;
494
- <a name="l00472"></a>00472 }
495
- <a name="l00473"></a>00473 alreadyRead += ret;
496
- <a name="l00474"></a>00474 } <span class="keywordflow">while</span> (alreadyRead &lt; <span class="keyword">sizeof</span>(size));
497
- <a name="l00475"></a>00475 size = ntohs(size);
418
+ <a name="l00396"></a>00396 <span class="comment">// See message_channel.rb for more info about negotiation.</span>
419
+ <a name="l00397"></a>00397 <span class="keywordflow">if</span> (negotiate) {
420
+ <a name="l00398"></a>00398 vector&lt;string&gt; args;
421
+ <a name="l00399"></a>00399
422
+ <a name="l00400"></a>00400 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args)) {
423
+ <a name="l00401"></a>00401 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"Unexpected end of stream encountered while pre-negotiating a file descriptor"</span>);
424
+ <a name="l00402"></a>00402 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (args.size() != 1 || args[0] != <span class="stringliteral">"pass IO"</span>) {
425
+ <a name="l00403"></a>00403 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"FD passing pre-negotiation message expected."</span>);
426
+ <a name="l00404"></a>00404 }
427
+ <a name="l00405"></a>00405 }
428
+ <a name="l00406"></a>00406
429
+ <a name="l00407"></a>00407 <span class="keyword">struct </span>msghdr msg;
430
+ <a name="l00408"></a>00408 <span class="keyword">struct </span>iovec vec;
431
+ <a name="l00409"></a>00409 <span class="keywordtype">char</span> dummy[1];
432
+ <a name="l00410"></a>00410 <span class="preprocessor"> #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)</span>
433
+ <a name="l00411"></a>00411 <span class="preprocessor"></span> <span class="keyword">struct </span>{
434
+ <a name="l00412"></a>00412 <span class="keyword">struct </span>cmsghdr header;
435
+ <a name="l00413"></a>00413 <span class="keywordtype">int</span> fd;
436
+ <a name="l00414"></a>00414 } control_data;
437
+ <a name="l00415"></a>00415 <span class="preprocessor"> #else</span>
438
+ <a name="l00416"></a>00416 <span class="preprocessor"></span> <span class="keywordtype">char</span> control_data[CMSG_SPACE(<span class="keyword">sizeof</span>(<span class="keywordtype">int</span>))];
439
+ <a name="l00417"></a>00417 <span class="preprocessor"> #endif</span>
440
+ <a name="l00418"></a>00418 <span class="preprocessor"></span> <span class="keyword">struct </span>cmsghdr *control_header;
441
+ <a name="l00419"></a>00419 <span class="keywordtype">int</span> ret;
442
+ <a name="l00420"></a>00420
443
+ <a name="l00421"></a>00421 msg.msg_name = NULL;
444
+ <a name="l00422"></a>00422 msg.msg_namelen = 0;
445
+ <a name="l00423"></a>00423
446
+ <a name="l00424"></a>00424 <span class="comment">/* Linux and Solaris require msg_iov to be non-NULL. */</span>
447
+ <a name="l00425"></a>00425 dummy[0] = <span class="charliteral">'\0'</span>;
448
+ <a name="l00426"></a>00426 vec.iov_base = dummy;
449
+ <a name="l00427"></a>00427 vec.iov_len = <span class="keyword">sizeof</span>(dummy);
450
+ <a name="l00428"></a>00428 msg.msg_iov = &amp;vec;
451
+ <a name="l00429"></a>00429 msg.msg_iovlen = 1;
452
+ <a name="l00430"></a>00430
453
+ <a name="l00431"></a>00431 msg.msg_control = (caddr_t) &amp;control_data;
454
+ <a name="l00432"></a>00432 msg.msg_controllen = <span class="keyword">sizeof</span>(control_data);
455
+ <a name="l00433"></a>00433 msg.msg_flags = 0;
456
+ <a name="l00434"></a>00434
457
+ <a name="l00435"></a>00435 control_header = CMSG_FIRSTHDR(&amp;msg);
458
+ <a name="l00436"></a>00436 control_header-&gt;cmsg_level = SOL_SOCKET;
459
+ <a name="l00437"></a>00437 control_header-&gt;cmsg_type = SCM_RIGHTS;
460
+ <a name="l00438"></a>00438 <span class="preprocessor"> #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)</span>
461
+ <a name="l00439"></a>00439 <span class="preprocessor"></span> control_header-&gt;cmsg_len = <span class="keyword">sizeof</span>(control_data);
462
+ <a name="l00440"></a>00440 control_data.fd = fileDescriptor;
463
+ <a name="l00441"></a>00441 <span class="preprocessor"> #else</span>
464
+ <a name="l00442"></a>00442 <span class="preprocessor"></span> control_header-&gt;cmsg_len = CMSG_LEN(<span class="keyword">sizeof</span>(<span class="keywordtype">int</span>));
465
+ <a name="l00443"></a>00443 memcpy(CMSG_DATA(control_header), &amp;fileDescriptor, <span class="keyword">sizeof</span>(<span class="keywordtype">int</span>));
466
+ <a name="l00444"></a>00444 <span class="preprocessor"> #endif</span>
467
+ <a name="l00445"></a>00445 <span class="preprocessor"></span>
468
+ <a name="l00446"></a>00446 ret = syscalls::sendmsg(fd, &amp;msg, 0);
469
+ <a name="l00447"></a>00447 <span class="keywordflow">if</span> (ret == -1) {
470
+ <a name="l00448"></a>00448 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot send file descriptor with sendmsg()"</span>, errno);
471
+ <a name="l00449"></a>00449 }
472
+ <a name="l00450"></a>00450
473
+ <a name="l00451"></a>00451 <span class="keywordflow">if</span> (negotiate) {
474
+ <a name="l00452"></a>00452 vector&lt;string&gt; args;
475
+ <a name="l00453"></a>00453
476
+ <a name="l00454"></a>00454 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(args)) {
477
+ <a name="l00455"></a>00455 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"Unexpected end of stream encountered while post-negotiating a file descriptor"</span>);
478
+ <a name="l00456"></a>00456 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (args.size() != 1 || args[0] != <span class="stringliteral">"got IO"</span>) {
479
+ <a name="l00457"></a>00457 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"FD passing post-negotiation message expected."</span>);
480
+ <a name="l00458"></a>00458 }
481
+ <a name="l00459"></a>00459 }
482
+ <a name="l00460"></a>00460 }
483
+ <a name="l00461"></a>00461 <span class="comment"></span>
484
+ <a name="l00462"></a>00462 <span class="comment"> /**</span>
485
+ <a name="l00463"></a>00463 <span class="comment"> * Read an array message from the underlying file descriptor.</span>
486
+ <a name="l00464"></a>00464 <span class="comment"> *</span>
487
+ <a name="l00465"></a>00465 <span class="comment"> * @param args The message will be put in this variable.</span>
488
+ <a name="l00466"></a>00466 <span class="comment"> * @return Whether end-of-file has been reached. If so, then the contents</span>
489
+ <a name="l00467"></a>00467 <span class="comment"> * of &lt;tt&gt;args&lt;/tt&gt; will be undefined.</span>
490
+ <a name="l00468"></a>00468 <span class="comment"> * @throws SystemException If an error occured while receiving the message.</span>
491
+ <a name="l00469"></a>00469 <span class="comment"> * @throws boost::thread_interrupted</span>
492
+ <a name="l00470"></a>00470 <span class="comment"> * @see write()</span>
493
+ <a name="l00471"></a>00471 <span class="comment"> */</span>
494
+ <a name="l00472"></a><a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e">00472</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">read</a>(vector&lt;string&gt; &amp;args) {
495
+ <a name="l00473"></a>00473 uint16_t size;
496
+ <a name="l00474"></a>00474 <span class="keywordtype">int</span> ret;
497
+ <a name="l00475"></a>00475 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> alreadyRead = 0;
498
498
  <a name="l00476"></a>00476
499
- <a name="l00477"></a>00477 <span class="keywordtype">string</span> buffer;
500
- <a name="l00478"></a>00478 args.clear();
501
- <a name="l00479"></a>00479 buffer.reserve(size);
502
- <a name="l00480"></a>00480 <span class="keywordflow">while</span> (buffer.size() &lt; size) {
503
- <a name="l00481"></a>00481 <span class="keywordtype">char</span> tmp[1024 * 8];
504
- <a name="l00482"></a>00482 ret = <a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">syscalls::read</a>(fd, tmp, min(size - buffer.size(), <span class="keyword">sizeof</span>(tmp)));
505
- <a name="l00483"></a>00483 <span class="keywordflow">if</span> (ret == -1) {
506
- <a name="l00484"></a>00484 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"read() failed"</span>, errno);
507
- <a name="l00485"></a>00485 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (ret == 0) {
508
- <a name="l00486"></a>00486 <span class="keywordflow">return</span> <span class="keyword">false</span>;
509
- <a name="l00487"></a>00487 }
510
- <a name="l00488"></a>00488 buffer.append(tmp, ret);
511
- <a name="l00489"></a>00489 }
512
- <a name="l00490"></a>00490
513
- <a name="l00491"></a>00491 <span class="keywordflow">if</span> (!buffer.empty()) {
514
- <a name="l00492"></a>00492 string::size_type start = 0, pos;
515
- <a name="l00493"></a>00493 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;const_buffer(buffer);
516
- <a name="l00494"></a>00494 <span class="keywordflow">while</span> ((pos = const_buffer.find(<span class="charliteral">'\0'</span>, start)) != string::npos) {
517
- <a name="l00495"></a>00495 args.push_back(const_buffer.substr(start, pos - start));
518
- <a name="l00496"></a>00496 start = pos + 1;
519
- <a name="l00497"></a>00497 }
520
- <a name="l00498"></a>00498 }
521
- <a name="l00499"></a>00499 <span class="keywordflow">return</span> <span class="keyword">true</span>;
522
- <a name="l00500"></a>00500 }
523
- <a name="l00501"></a>00501 <span class="comment"></span>
524
- <a name="l00502"></a>00502 <span class="comment"> /**</span>
525
- <a name="l00503"></a>00503 <span class="comment"> * Read a 32-bit big-endian unsigned integer from the underlying file descriptor.</span>
526
- <a name="l00504"></a>00504 <span class="comment"> *</span>
527
- <a name="l00505"></a>00505 <span class="comment"> * @param value Upon success, the read value will be stored in here.</span>
528
- <a name="l00506"></a>00506 <span class="comment"> * @param timeout A pointer to an integer, representing the maximum number of</span>
529
- <a name="l00507"></a>00507 <span class="comment"> * milliseconds to spend on reading the entire integer.</span>
530
- <a name="l00508"></a>00508 <span class="comment"> * A TimeoutException will be thrown if the timeout expires.</span>
531
- <a name="l00509"></a>00509 <span class="comment"> * If no exception is thrown, the the amount of time spent on waiting</span>
532
- <a name="l00510"></a>00510 <span class="comment"> * will be deducted from &lt;tt&gt;*timeout&lt;/tt&gt;.</span>
533
- <a name="l00511"></a>00511 <span class="comment"> * Pass NULL if you do not want to enforce any time limits.</span>
534
- <a name="l00512"></a>00512 <span class="comment"> * @return True if a value was read, false if EOF was reached before all data can be</span>
535
- <a name="l00513"></a>00513 <span class="comment"> * read.</span>
536
- <a name="l00514"></a>00514 <span class="comment"> * @throws SystemException An error occurred while reading data from the file descriptor.</span>
537
- <a name="l00515"></a>00515 <span class="comment"> * @throws boost::thread_interrupted</span>
538
- <a name="l00516"></a>00516 <span class="comment"> */</span>
539
- <a name="l00517"></a><a class="code" href="classPassenger_1_1MessageChannel.html#7b0c67852ea8ab455af75b1037c7f8b6">00517</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1MessageChannel.html#7b0c67852ea8ab455af75b1037c7f8b6" title="Read a 32-bit big-endian unsigned integer from the underlying file descriptor.">readUint32</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> &amp;value, <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span> *timeout = NULL) {
540
- <a name="l00518"></a>00518 uint32_t temp;
541
- <a name="l00519"></a>00519
542
- <a name="l00520"></a>00520 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1MessageChannel.html#b471dc1888f030e20ed23068a160ec2a" title="Read exactly size bytes of data from the underlying file descriptor, and put the...">readRaw</a>(&amp;temp, <span class="keyword">sizeof</span>(uint32_t), timeout)) {
543
- <a name="l00521"></a>00521 <span class="keywordflow">return</span> <span class="keyword">false</span>;
544
- <a name="l00522"></a>00522 } <span class="keywordflow">else</span> {
545
- <a name="l00523"></a>00523 value = ntohl(temp);
546
- <a name="l00524"></a>00524 <span class="keywordflow">return</span> <span class="keyword">true</span>;
547
- <a name="l00525"></a>00525 }
548
- <a name="l00526"></a>00526 }
549
- <a name="l00527"></a>00527 <span class="comment"></span>
550
- <a name="l00528"></a>00528 <span class="comment"> /**</span>
551
- <a name="l00529"></a>00529 <span class="comment"> * Read a scalar message from the underlying file descriptor.</span>
552
- <a name="l00530"></a>00530 <span class="comment"> *</span>
553
- <a name="l00531"></a>00531 <span class="comment"> * @param output The message will be put in here.</span>
554
- <a name="l00532"></a>00532 <span class="comment"> * @param maxSize The maximum number of bytes that may be read. If the</span>
555
- <a name="l00533"></a>00533 <span class="comment"> * scalar to read is larger than this, then a SecurityException</span>
556
- <a name="l00534"></a>00534 <span class="comment"> * will be thrown. Set to 0 for no size limit.</span>
557
- <a name="l00535"></a>00535 <span class="comment"> * @param timeout A pointer to an integer, representing the maximum number of</span>
558
- <a name="l00536"></a>00536 <span class="comment"> * milliseconds to spend on reading the entire scalar.</span>
559
- <a name="l00537"></a>00537 <span class="comment"> * A TimeoutException will be thrown if unable to read the entire</span>
560
- <a name="l00538"></a>00538 <span class="comment"> * scalar within this time period.</span>
561
- <a name="l00539"></a>00539 <span class="comment"> * If no exception is thrown, the the amount of time spent on waiting</span>
562
- <a name="l00540"></a>00540 <span class="comment"> * will be deducted from &lt;tt&gt;*timeout&lt;/tt&gt;.</span>
563
- <a name="l00541"></a>00541 <span class="comment"> * Pass NULL if you do not want to enforce any time limits.</span>
564
- <a name="l00542"></a>00542 <span class="comment"> * @returns Whether end-of-file was reached during reading.</span>
565
- <a name="l00543"></a>00543 <span class="comment"> * @throws SystemException An error occured while reading data from the file descriptor.</span>
566
- <a name="l00544"></a>00544 <span class="comment"> * @throws SecurityException There is more data to read than allowed by maxSize.</span>
567
- <a name="l00545"></a>00545 <span class="comment"> * @throws TimeoutException Unable to read the entire scalar within &lt;tt&gt;timeout&lt;/tt&gt;</span>
568
- <a name="l00546"></a>00546 <span class="comment"> * milliseconds.</span>
569
- <a name="l00547"></a>00547 <span class="comment"> * @throws boost::thread_interrupted</span>
570
- <a name="l00548"></a>00548 <span class="comment"> * @see writeScalar()</span>
571
- <a name="l00549"></a>00549 <span class="comment"> */</span>
572
- <a name="l00550"></a><a class="code" href="classPassenger_1_1MessageChannel.html#1f3cf672b566166ed920c2bba4d19604">00550</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1MessageChannel.html#1f3cf672b566166ed920c2bba4d19604" title="Read a scalar message from the underlying file descriptor.">readScalar</a>(<span class="keywordtype">string</span> &amp;output, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> maxSize = 0, <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span> *timeout = NULL) {
573
- <a name="l00551"></a>00551 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> size;
574
- <a name="l00552"></a>00552 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> remaining;
575
- <a name="l00553"></a>00553
576
- <a name="l00554"></a>00554 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1MessageChannel.html#7b0c67852ea8ab455af75b1037c7f8b6" title="Read a 32-bit big-endian unsigned integer from the underlying file descriptor.">readUint32</a>(size, timeout)) {
577
- <a name="l00555"></a>00555 <span class="keywordflow">return</span> <span class="keyword">false</span>;
578
- <a name="l00556"></a>00556 }
579
- <a name="l00557"></a>00557
580
- <a name="l00558"></a>00558 <span class="keywordflow">if</span> (maxSize != 0 &amp;&amp; size &gt; maxSize) {
581
- <a name="l00559"></a>00559 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SecurityException.html" title="Represents some kind of security error.">SecurityException</a>(<span class="stringliteral">"There is more data available than is allowed by the size limit."</span>);
582
- <a name="l00560"></a>00560 }
583
- <a name="l00561"></a>00561
584
- <a name="l00562"></a>00562 output.clear();
585
- <a name="l00563"></a>00563 output.reserve(size);
586
- <a name="l00564"></a>00564 remaining = size;
587
- <a name="l00565"></a>00565 <span class="keywordflow">if</span> (OXT_LIKELY(remaining &gt; 0)) {
588
- <a name="l00566"></a>00566 <span class="keywordtype">char</span> buf[1024 * 32];
589
- <a name="l00567"></a>00567 <span class="comment">// Wipe the buffer when we're done; it might contain sensitive data.</span>
590
- <a name="l00568"></a>00568 <a class="code" href="classPassenger_1_1MemZeroGuard.html" title="Fills the given memory space or string with zeroes when a MemoryZeroGuard object...">MemZeroGuard</a> g(buf, <span class="keyword">sizeof</span>(buf));
591
- <a name="l00569"></a>00569
592
- <a name="l00570"></a>00570 <span class="keywordflow">while</span> (remaining &gt; 0) {
593
- <a name="l00571"></a>00571 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> blockSize = min((<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>) <span class="keyword">sizeof</span>(buf), remaining);
594
- <a name="l00572"></a>00572
595
- <a name="l00573"></a>00573 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1MessageChannel.html#b471dc1888f030e20ed23068a160ec2a" title="Read exactly size bytes of data from the underlying file descriptor, and put the...">readRaw</a>(buf, blockSize, timeout)) {
596
- <a name="l00574"></a>00574 <span class="keywordflow">return</span> <span class="keyword">false</span>;
597
- <a name="l00575"></a>00575 }
598
- <a name="l00576"></a>00576 output.append(buf, blockSize);
599
- <a name="l00577"></a>00577 remaining -= blockSize;
600
- <a name="l00578"></a>00578 }
601
- <a name="l00579"></a>00579 }
602
- <a name="l00580"></a>00580 <span class="keywordflow">return</span> <span class="keyword">true</span>;
603
- <a name="l00581"></a>00581 }
604
- <a name="l00582"></a>00582 <span class="comment"></span>
605
- <a name="l00583"></a>00583 <span class="comment"> /**</span>
606
- <a name="l00584"></a>00584 <span class="comment"> * Read exactly &lt;tt&gt;size&lt;/tt&gt; bytes of data from the underlying file descriptor,</span>
607
- <a name="l00585"></a>00585 <span class="comment"> * and put the result in &lt;tt&gt;buf&lt;/tt&gt;. If end-of-file has been reached, or if</span>
608
- <a name="l00586"></a>00586 <span class="comment"> * end-of-file was encountered before &lt;tt&gt;size&lt;/tt&gt; bytes have been read, then</span>
609
- <a name="l00587"></a>00587 <span class="comment"> * &lt;tt&gt;false&lt;/tt&gt; will be returned. Otherwise (i.e. if the read was successful),</span>
610
- <a name="l00588"></a>00588 <span class="comment"> * &lt;tt&gt;true&lt;/tt&gt; will be returned.</span>
611
- <a name="l00589"></a>00589 <span class="comment"> *</span>
612
- <a name="l00590"></a>00590 <span class="comment"> * @param buf The buffer to place the read data in. This buffer must be at least</span>
613
- <a name="l00591"></a>00591 <span class="comment"> * &lt;tt&gt;size&lt;/tt&gt; bytes long.</span>
614
- <a name="l00592"></a>00592 <span class="comment"> * @param size The number of bytes to read.</span>
615
- <a name="l00593"></a>00593 <span class="comment"> * @param timeout A pointer to an integer, which specifies the maximum number of</span>
616
- <a name="l00594"></a>00594 <span class="comment"> * milliseconds that may be spent on reading the &lt;tt&gt;size&lt;/tt&gt; bytes</span>
617
- <a name="l00595"></a>00595 <span class="comment"> * of data. If the timeout expired then TimeoutException will be</span>
618
- <a name="l00596"></a>00596 <span class="comment"> * thrown.</span>
619
- <a name="l00597"></a>00597 <span class="comment"> * If this function returns without throwing an exception, then the</span>
620
- <a name="l00598"></a>00598 <span class="comment"> * total number of milliseconds spent on reading will be deducted</span>
621
- <a name="l00599"></a>00599 <span class="comment"> * from &lt;tt&gt;timeout&lt;/tt&gt;.</span>
622
- <a name="l00600"></a>00600 <span class="comment"> * Pass NULL if you do not want to enforce a timeout.</span>
623
- <a name="l00601"></a>00601 <span class="comment"> * @return Whether reading was successful or whether EOF was reached.</span>
624
- <a name="l00602"></a>00602 <span class="comment"> * @pre buf != NULL</span>
625
- <a name="l00603"></a>00603 <span class="comment"> * @throws SystemException Something went wrong during reading.</span>
626
- <a name="l00604"></a>00604 <span class="comment"> * @throws TimeoutException Unable to read &lt;tt&gt;size&lt;/tt&gt; bytes of data within</span>
627
- <a name="l00605"></a>00605 <span class="comment"> * &lt;tt&gt;timeout&lt;/tt&gt; milliseconds.</span>
628
- <a name="l00606"></a>00606 <span class="comment"> * @throws boost::thread_interrupted</span>
629
- <a name="l00607"></a>00607 <span class="comment"> * @see writeRaw()</span>
630
- <a name="l00608"></a>00608 <span class="comment"> */</span>
631
- <a name="l00609"></a><a class="code" href="classPassenger_1_1MessageChannel.html#b471dc1888f030e20ed23068a160ec2a">00609</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1MessageChannel.html#b471dc1888f030e20ed23068a160ec2a" title="Read exactly size bytes of data from the underlying file descriptor, and put the...">readRaw</a>(<span class="keywordtype">void</span> *buf, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> size, <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span> *timeout = NULL) {
632
- <a name="l00610"></a>00610 ssize_t ret;
633
- <a name="l00611"></a>00611 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> alreadyRead = 0;
634
- <a name="l00612"></a>00612
635
- <a name="l00613"></a>00613 <span class="keywordflow">while</span> (alreadyRead &lt; size) {
636
- <a name="l00614"></a>00614 <span class="keywordflow">if</span> (timeout != NULL &amp;&amp; !<a class="code" href="classPassenger_1_1MessageChannel.html#c2407ed109785b49794989507c570149" title="Waits at most *timeout milliseconds for the file descriptor to become readable.">waitUntilReadable</a>(timeout)) {
637
- <a name="l00615"></a>00615 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1TimeoutException.html" title="An exception indicating that some timeout expired.">TimeoutException</a>(<span class="stringliteral">"Cannot read enough data within the specified timeout."</span>);
638
- <a name="l00616"></a>00616 }
639
- <a name="l00617"></a>00617 ret = <a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">syscalls::read</a>(fd, (<span class="keywordtype">char</span> *) buf + alreadyRead, size - alreadyRead);
640
- <a name="l00618"></a>00618 <span class="keywordflow">if</span> (ret == -1) {
641
- <a name="l00619"></a>00619 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"read() failed"</span>, errno);
642
- <a name="l00620"></a>00620 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (ret == 0) {
643
- <a name="l00621"></a>00621 <span class="keywordflow">return</span> <span class="keyword">false</span>;
644
- <a name="l00622"></a>00622 } <span class="keywordflow">else</span> {
645
- <a name="l00623"></a>00623 alreadyRead += ret;
646
- <a name="l00624"></a>00624 }
647
- <a name="l00625"></a>00625 }
648
- <a name="l00626"></a>00626 <span class="keywordflow">return</span> <span class="keyword">true</span>;
649
- <a name="l00627"></a>00627 }
650
- <a name="l00628"></a>00628 <span class="comment"></span>
651
- <a name="l00629"></a>00629 <span class="comment"> /**</span>
652
- <a name="l00630"></a>00630 <span class="comment"> * Waits at most &lt;tt&gt;*timeout&lt;/tt&gt; milliseconds for the file descriptor to become readable.</span>
653
- <a name="l00631"></a>00631 <span class="comment"> * Returns true if it become readable within the timeout, false if the timeout expired.</span>
654
- <a name="l00632"></a>00632 <span class="comment"> *</span>
655
- <a name="l00633"></a>00633 <span class="comment"> * &lt;tt&gt;*timeout&lt;/tt&gt; may be 0, in which case this method will check whether the file</span>
656
- <a name="l00634"></a>00634 <span class="comment"> * descriptor is readable, and immediately returns without waiting.</span>
657
- <a name="l00635"></a>00635 <span class="comment"> *</span>
658
- <a name="l00636"></a>00636 <span class="comment"> * If no exception is thrown, this method deducts the number of milliseconds that has</span>
659
- <a name="l00637"></a>00637 <span class="comment"> * passed from &lt;tt&gt;*timeout&lt;/tt&gt;.</span>
660
- <a name="l00638"></a>00638 <span class="comment"> *</span>
661
- <a name="l00639"></a>00639 <span class="comment"> * @throws SystemException</span>
662
- <a name="l00640"></a>00640 <span class="comment"> * @throws boost::thread_interrupted</span>
663
- <a name="l00641"></a>00641 <span class="comment"> */</span>
664
- <a name="l00642"></a><a class="code" href="classPassenger_1_1MessageChannel.html#c2407ed109785b49794989507c570149">00642</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1MessageChannel.html#c2407ed109785b49794989507c570149" title="Waits at most *timeout milliseconds for the file descriptor to become readable.">waitUntilReadable</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span> *timeout) {
665
- <a name="l00643"></a>00643 fd_set fds;
666
- <a name="l00644"></a>00644 <span class="keyword">struct </span>timeval tv;
667
- <a name="l00645"></a>00645 <span class="keywordtype">int</span> ret;
668
- <a name="l00646"></a>00646
669
- <a name="l00647"></a>00647 FD_ZERO(&amp;fds);
670
- <a name="l00648"></a>00648 FD_SET(fd, &amp;fds);
671
- <a name="l00649"></a>00649 tv.tv_sec = *timeout / 1000;
672
- <a name="l00650"></a>00650 tv.tv_usec = *timeout % 1000 * 1000;
673
- <a name="l00651"></a>00651
674
- <a name="l00652"></a>00652 Timer timer;
675
- <a name="l00653"></a>00653 ret = syscalls::select(fd + 1, &amp;fds, NULL, NULL, &amp;tv);
676
- <a name="l00654"></a>00654 <span class="keywordflow">if</span> (ret == -1) {
677
- <a name="l00655"></a>00655 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"select() failed"</span>, errno);
678
- <a name="l00656"></a>00656 } <span class="keywordflow">else</span> {
679
- <a name="l00657"></a>00657 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span> elapsed = timer.elapsed();
680
- <a name="l00658"></a>00658 <span class="keywordflow">if</span> (elapsed &gt; *timeout) {
681
- <a name="l00659"></a>00659 *timeout = 0;
682
- <a name="l00660"></a>00660 } <span class="keywordflow">else</span> {
683
- <a name="l00661"></a>00661 *timeout -= elapsed;
684
- <a name="l00662"></a>00662 }
685
- <a name="l00663"></a>00663 <span class="keywordflow">return</span> ret != 0;
686
- <a name="l00664"></a>00664 }
687
- <a name="l00665"></a>00665 }
688
- <a name="l00666"></a>00666 <span class="comment"></span>
689
- <a name="l00667"></a>00667 <span class="comment"> /**</span>
690
- <a name="l00668"></a>00668 <span class="comment"> * Receive a file descriptor, which had been passed over the underlying</span>
691
- <a name="l00669"></a>00669 <span class="comment"> * file descriptor.</span>
692
- <a name="l00670"></a>00670 <span class="comment"> *</span>
693
- <a name="l00671"></a>00671 <span class="comment"> * @param negotiate See Ruby's MessageChannel#send_io method's comments.</span>
694
- <a name="l00672"></a>00672 <span class="comment"> * @return The passed file descriptor.</span>
695
- <a name="l00673"></a>00673 <span class="comment"> * @throws SystemException If something went wrong during the</span>
696
- <a name="l00674"></a>00674 <span class="comment"> * receiving of a file descriptor. Perhaps the underlying</span>
697
- <a name="l00675"></a>00675 <span class="comment"> * file descriptor isn't a Unix socket.</span>
698
- <a name="l00676"></a>00676 <span class="comment"> * @throws IOException Whatever was received doesn't seem to be a</span>
699
- <a name="l00677"></a>00677 <span class="comment"> * file descriptor.</span>
700
- <a name="l00678"></a>00678 <span class="comment"> * @throws boost::thread_interrupted</span>
701
- <a name="l00679"></a>00679 <span class="comment"> */</span>
702
- <a name="l00680"></a><a class="code" href="classPassenger_1_1MessageChannel.html#1a28ba9d078f38f2831673092ac9dcbc">00680</a> <span class="keywordtype">int</span> <a class="code" href="classPassenger_1_1MessageChannel.html#1a28ba9d078f38f2831673092ac9dcbc" title="Receive a file descriptor, which had been passed over the underlying file descriptor...">readFileDescriptor</a>(<span class="keywordtype">bool</span> negotiate = <span class="keyword">true</span>) {
703
- <a name="l00681"></a>00681 <span class="keywordflow">if</span> (negotiate) {
704
- <a name="l00682"></a>00682 <a class="code" href="classPassenger_1_1MessageChannel.html#150f68bc47e060dcc6ca35bee047914d" title="Send an array message, which consists of the given elements, over the underlying...">write</a>(<span class="stringliteral">"pass IO"</span>, NULL);
705
- <a name="l00683"></a>00683 }
706
- <a name="l00684"></a>00684
707
- <a name="l00685"></a>00685 <span class="keyword">struct </span>msghdr msg;
708
- <a name="l00686"></a>00686 <span class="keyword">struct </span>iovec vec;
709
- <a name="l00687"></a>00687 <span class="keywordtype">char</span> dummy[1];
710
- <a name="l00688"></a>00688 <span class="preprocessor"> #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)</span>
711
- <a name="l00689"></a>00689 <span class="preprocessor"></span> <span class="comment">// File descriptor passing macros (CMSG_*) seem to be broken</span>
712
- <a name="l00690"></a>00690 <span class="comment">// on 64-bit MacOS X. This structure works around the problem.</span>
713
- <a name="l00691"></a>00691 <span class="keyword">struct </span>{
714
- <a name="l00692"></a>00692 <span class="keyword">struct </span>cmsghdr header;
715
- <a name="l00693"></a>00693 <span class="keywordtype">int</span> fd;
716
- <a name="l00694"></a>00694 } control_data;
717
- <a name="l00695"></a>00695 <span class="preprocessor"> #define EXPECTED_CMSG_LEN sizeof(control_data)</span>
718
- <a name="l00696"></a>00696 <span class="preprocessor"></span><span class="preprocessor"> #else</span>
719
- <a name="l00697"></a>00697 <span class="preprocessor"></span> <span class="keywordtype">char</span> control_data[CMSG_SPACE(<span class="keyword">sizeof</span>(<span class="keywordtype">int</span>))];
720
- <a name="l00698"></a>00698 <span class="preprocessor"> #define EXPECTED_CMSG_LEN CMSG_LEN(sizeof(int))</span>
721
- <a name="l00699"></a>00699 <span class="preprocessor"></span><span class="preprocessor"> #endif</span>
722
- <a name="l00700"></a>00700 <span class="preprocessor"></span> <span class="keyword">struct </span>cmsghdr *control_header;
723
- <a name="l00701"></a>00701 <span class="keywordtype">int</span> ret;
724
- <a name="l00702"></a>00702
725
- <a name="l00703"></a>00703 msg.msg_name = NULL;
726
- <a name="l00704"></a>00704 msg.msg_namelen = 0;
727
- <a name="l00705"></a>00705
728
- <a name="l00706"></a>00706 dummy[0] = <span class="charliteral">'\0'</span>;
729
- <a name="l00707"></a>00707 vec.iov_base = dummy;
730
- <a name="l00708"></a>00708 vec.iov_len = <span class="keyword">sizeof</span>(dummy);
731
- <a name="l00709"></a>00709 msg.msg_iov = &amp;vec;
732
- <a name="l00710"></a>00710 msg.msg_iovlen = 1;
733
- <a name="l00711"></a>00711
734
- <a name="l00712"></a>00712 msg.msg_control = (caddr_t) &amp;control_data;
735
- <a name="l00713"></a>00713 msg.msg_controllen = <span class="keyword">sizeof</span>(control_data);
736
- <a name="l00714"></a>00714 msg.msg_flags = 0;
737
- <a name="l00715"></a>00715
738
- <a name="l00716"></a>00716 ret = syscalls::recvmsg(fd, &amp;msg, 0);
739
- <a name="l00717"></a>00717 <span class="keywordflow">if</span> (ret == -1) {
740
- <a name="l00718"></a>00718 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot read file descriptor with recvmsg()"</span>, errno);
741
- <a name="l00719"></a>00719 }
742
- <a name="l00720"></a>00720
743
- <a name="l00721"></a>00721 control_header = CMSG_FIRSTHDR(&amp;msg);
744
- <a name="l00722"></a>00722 <span class="keywordflow">if</span> (control_header == NULL) {
745
- <a name="l00723"></a>00723 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"No valid file descriptor received."</span>);
746
- <a name="l00724"></a>00724 }
747
- <a name="l00725"></a>00725 <span class="keywordflow">if</span> (control_header-&gt;cmsg_len != EXPECTED_CMSG_LEN
748
- <a name="l00726"></a>00726 || control_header-&gt;cmsg_level != SOL_SOCKET
749
- <a name="l00727"></a>00727 || control_header-&gt;cmsg_type != SCM_RIGHTS) {
750
- <a name="l00728"></a>00728 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"No valid file descriptor received."</span>);
751
- <a name="l00729"></a>00729 }
752
- <a name="l00730"></a>00730 <span class="preprocessor"> #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)</span>
753
- <a name="l00731"></a>00731 <span class="preprocessor"></span> <span class="keywordflow">return</span> control_data.fd;
754
- <a name="l00732"></a>00732 <span class="preprocessor"> #else</span>
755
- <a name="l00733"></a>00733 <span class="preprocessor"></span> <span class="keywordflow">return</span> *((<span class="keywordtype">int</span> *) CMSG_DATA(control_header));
756
- <a name="l00734"></a>00734 <span class="preprocessor"> #endif</span>
757
- <a name="l00735"></a>00735 <span class="preprocessor"></span> }
758
- <a name="l00736"></a>00736 <span class="comment"></span>
759
- <a name="l00737"></a>00737 <span class="comment"> /**</span>
760
- <a name="l00738"></a>00738 <span class="comment"> * Set the timeout value for reading data from this channel.</span>
761
- <a name="l00739"></a>00739 <span class="comment"> * If no data can be read within the timeout period, then a</span>
762
- <a name="l00740"></a>00740 <span class="comment"> * SystemException will be thrown by one of the read methods,</span>
763
- <a name="l00741"></a>00741 <span class="comment"> * with error code EAGAIN or EWOULDBLOCK.</span>
764
- <a name="l00742"></a>00742 <span class="comment"> *</span>
765
- <a name="l00743"></a>00743 <span class="comment"> * @param msec The timeout, in milliseconds. If 0 is given,</span>
766
- <a name="l00744"></a>00744 <span class="comment"> * there will be no timeout.</span>
767
- <a name="l00745"></a>00745 <span class="comment"> * @throws SystemException Cannot set the timeout.</span>
768
- <a name="l00746"></a>00746 <span class="comment"> */</span>
769
- <a name="l00747"></a><a class="code" href="classPassenger_1_1MessageChannel.html#eb69bffbbb148c9bc8662e20b416c4e2">00747</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1MessageChannel.html#eb69bffbbb148c9bc8662e20b416c4e2" title="Set the timeout value for reading data from this channel.">setReadTimeout</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> msec) {
770
- <a name="l00748"></a>00748 <span class="comment">// See the comment for setWriteTimeout().</span>
771
- <a name="l00749"></a>00749 <span class="keyword">struct </span>timeval tv;
772
- <a name="l00750"></a>00750 <span class="keywordtype">int</span> ret;
773
- <a name="l00751"></a>00751
774
- <a name="l00752"></a>00752 tv.tv_sec = msec / 1000;
775
- <a name="l00753"></a>00753 tv.tv_usec = msec % 1000 * 1000;
776
- <a name="l00754"></a>00754 ret = syscalls::setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
777
- <a name="l00755"></a>00755 &amp;tv, <span class="keyword">sizeof</span>(tv));
778
- <a name="l00756"></a>00756 <span class="preprocessor"> #ifndef __SOLARIS__</span>
779
- <a name="l00757"></a>00757 <span class="preprocessor"></span> <span class="comment">// SO_RCVTIMEO is unimplemented and returns an error on Solaris</span>
780
- <a name="l00758"></a>00758 <span class="comment">// 9 and 10 SPARC. Seems to work okay without it.</span>
781
- <a name="l00759"></a>00759 <span class="keywordflow">if</span> (ret == -1) {
782
- <a name="l00760"></a>00760 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot set read timeout for socket"</span>, errno);
783
- <a name="l00761"></a>00761 }
784
- <a name="l00762"></a>00762 <span class="preprocessor"> #endif</span>
785
- <a name="l00763"></a>00763 <span class="preprocessor"></span> }
786
- <a name="l00764"></a>00764 <span class="comment"></span>
787
- <a name="l00765"></a>00765 <span class="comment"> /**</span>
788
- <a name="l00766"></a>00766 <span class="comment"> * Set the timeout value for writing data to this channel.</span>
789
- <a name="l00767"></a>00767 <span class="comment"> * If no data can be written within the timeout period, then a</span>
790
- <a name="l00768"></a>00768 <span class="comment"> * SystemException will be thrown, with error code EAGAIN or</span>
791
- <a name="l00769"></a>00769 <span class="comment"> * EWOULDBLOCK.</span>
792
- <a name="l00770"></a>00770 <span class="comment"> *</span>
793
- <a name="l00771"></a>00771 <span class="comment"> * @param msec The timeout, in milliseconds. If 0 is given,</span>
794
- <a name="l00772"></a>00772 <span class="comment"> * there will be no timeout.</span>
795
- <a name="l00773"></a>00773 <span class="comment"> * @throws SystemException Cannot set the timeout.</span>
796
- <a name="l00774"></a>00774 <span class="comment"> */</span>
797
- <a name="l00775"></a><a class="code" href="classPassenger_1_1MessageChannel.html#77c5d7c47f387cf43992ebeb14e3c6c7">00775</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1MessageChannel.html#77c5d7c47f387cf43992ebeb14e3c6c7" title="Set the timeout value for writing data to this channel.">setWriteTimeout</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> msec) {
798
- <a name="l00776"></a>00776 <span class="comment">// People say that SO_RCVTIMEO/SO_SNDTIMEO are unreliable and</span>
799
- <a name="l00777"></a>00777 <span class="comment">// not well-implemented on all platforms.</span>
800
- <a name="l00778"></a>00778 <span class="comment">// http://www.developerweb.net/forum/archive/index.php/t-3439.html</span>
801
- <a name="l00779"></a>00779 <span class="comment">// That's why we use APR's timeout facilities as well (see Hooks.cpp).</span>
802
- <a name="l00780"></a>00780 <span class="keyword">struct </span>timeval tv;
803
- <a name="l00781"></a>00781 <span class="keywordtype">int</span> ret;
804
- <a name="l00782"></a>00782
805
- <a name="l00783"></a>00783 tv.tv_sec = msec / 1000;
806
- <a name="l00784"></a>00784 tv.tv_usec = msec % 1000 * 1000;
807
- <a name="l00785"></a>00785 ret = syscalls::setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
808
- <a name="l00786"></a>00786 &amp;tv, <span class="keyword">sizeof</span>(tv));
809
- <a name="l00787"></a>00787 <span class="preprocessor"> #ifndef __SOLARIS__</span>
810
- <a name="l00788"></a>00788 <span class="preprocessor"></span> <span class="comment">// SO_SNDTIMEO is unimplemented and returns an error on Solaris</span>
811
- <a name="l00789"></a>00789 <span class="comment">// 9 and 10 SPARC. Seems to work okay without it.</span>
812
- <a name="l00790"></a>00790 <span class="keywordflow">if</span> (ret == -1) {
813
- <a name="l00791"></a>00791 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot set read timeout for socket"</span>, errno);
814
- <a name="l00792"></a>00792 }
815
- <a name="l00793"></a>00793 <span class="preprocessor"> #endif</span>
816
- <a name="l00794"></a>00794 <span class="preprocessor"></span> }
817
- <a name="l00795"></a>00795 };
818
- <a name="l00796"></a>00796
819
- <a name="l00797"></a>00797 } <span class="comment">// namespace Passenger</span>
820
- <a name="l00798"></a>00798
821
- <a name="l00799"></a>00799 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_MESSAGE_CHANNEL_H_ */</span>
499
+ <a name="l00477"></a>00477 <span class="keywordflow">do</span> {
500
+ <a name="l00478"></a>00478 ret = <a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">syscalls::read</a>(fd, (<span class="keywordtype">char</span> *) &amp;size + alreadyRead, <span class="keyword">sizeof</span>(size) - alreadyRead);
501
+ <a name="l00479"></a>00479 <span class="keywordflow">if</span> (ret == -1) {
502
+ <a name="l00480"></a>00480 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"read() failed"</span>, errno);
503
+ <a name="l00481"></a>00481 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (ret == 0) {
504
+ <a name="l00482"></a>00482 <span class="keywordflow">return</span> <span class="keyword">false</span>;
505
+ <a name="l00483"></a>00483 }
506
+ <a name="l00484"></a>00484 alreadyRead += ret;
507
+ <a name="l00485"></a>00485 } <span class="keywordflow">while</span> (alreadyRead &lt; <span class="keyword">sizeof</span>(size));
508
+ <a name="l00486"></a>00486 size = ntohs(size);
509
+ <a name="l00487"></a>00487
510
+ <a name="l00488"></a>00488 <span class="keywordtype">string</span> buffer;
511
+ <a name="l00489"></a>00489 args.clear();
512
+ <a name="l00490"></a>00490 buffer.reserve(size);
513
+ <a name="l00491"></a>00491 <span class="keywordflow">while</span> (buffer.size() &lt; size) {
514
+ <a name="l00492"></a>00492 <span class="keywordtype">char</span> tmp[1024 * 8];
515
+ <a name="l00493"></a>00493 ret = <a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">syscalls::read</a>(fd, tmp, min(size - buffer.size(), <span class="keyword">sizeof</span>(tmp)));
516
+ <a name="l00494"></a>00494 <span class="keywordflow">if</span> (ret == -1) {
517
+ <a name="l00495"></a>00495 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"read() failed"</span>, errno);
518
+ <a name="l00496"></a>00496 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (ret == 0) {
519
+ <a name="l00497"></a>00497 <span class="keywordflow">return</span> <span class="keyword">false</span>;
520
+ <a name="l00498"></a>00498 }
521
+ <a name="l00499"></a>00499 buffer.append(tmp, ret);
522
+ <a name="l00500"></a>00500 }
523
+ <a name="l00501"></a>00501
524
+ <a name="l00502"></a>00502 <span class="keywordflow">if</span> (!buffer.empty()) {
525
+ <a name="l00503"></a>00503 string::size_type start = 0, pos;
526
+ <a name="l00504"></a>00504 <span class="keyword">const</span> <span class="keywordtype">string</span> &amp;const_buffer(buffer);
527
+ <a name="l00505"></a>00505 <span class="keywordflow">while</span> ((pos = const_buffer.find(<span class="charliteral">'\0'</span>, start)) != string::npos) {
528
+ <a name="l00506"></a>00506 args.push_back(const_buffer.substr(start, pos - start));
529
+ <a name="l00507"></a>00507 start = pos + 1;
530
+ <a name="l00508"></a>00508 }
531
+ <a name="l00509"></a>00509 }
532
+ <a name="l00510"></a>00510 <span class="keywordflow">return</span> <span class="keyword">true</span>;
533
+ <a name="l00511"></a>00511 }
534
+ <a name="l00512"></a>00512 <span class="comment"></span>
535
+ <a name="l00513"></a>00513 <span class="comment"> /**</span>
536
+ <a name="l00514"></a>00514 <span class="comment"> * Read a 32-bit big-endian unsigned integer from the underlying file descriptor.</span>
537
+ <a name="l00515"></a>00515 <span class="comment"> *</span>
538
+ <a name="l00516"></a>00516 <span class="comment"> * @param value Upon success, the read value will be stored in here.</span>
539
+ <a name="l00517"></a>00517 <span class="comment"> * @param timeout A pointer to an integer, representing the maximum number of</span>
540
+ <a name="l00518"></a>00518 <span class="comment"> * milliseconds to spend on reading the entire integer.</span>
541
+ <a name="l00519"></a>00519 <span class="comment"> * A TimeoutException will be thrown if the timeout expires.</span>
542
+ <a name="l00520"></a>00520 <span class="comment"> * If no exception is thrown, the the amount of time spent on waiting</span>
543
+ <a name="l00521"></a>00521 <span class="comment"> * will be deducted from &lt;tt&gt;*timeout&lt;/tt&gt;.</span>
544
+ <a name="l00522"></a>00522 <span class="comment"> * Pass NULL if you do not want to enforce any time limits.</span>
545
+ <a name="l00523"></a>00523 <span class="comment"> * @return True if a value was read, false if EOF was reached before all data can be</span>
546
+ <a name="l00524"></a>00524 <span class="comment"> * read.</span>
547
+ <a name="l00525"></a>00525 <span class="comment"> * @throws SystemException An error occurred while reading data from the file descriptor.</span>
548
+ <a name="l00526"></a>00526 <span class="comment"> * @throws boost::thread_interrupted</span>
549
+ <a name="l00527"></a>00527 <span class="comment"> */</span>
550
+ <a name="l00528"></a><a class="code" href="classPassenger_1_1MessageChannel.html#7b0c67852ea8ab455af75b1037c7f8b6">00528</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1MessageChannel.html#7b0c67852ea8ab455af75b1037c7f8b6" title="Read a 32-bit big-endian unsigned integer from the underlying file descriptor.">readUint32</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> &amp;value, <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span> *timeout = NULL) {
551
+ <a name="l00529"></a>00529 uint32_t temp;
552
+ <a name="l00530"></a>00530
553
+ <a name="l00531"></a>00531 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1MessageChannel.html#b471dc1888f030e20ed23068a160ec2a" title="Read exactly size bytes of data from the underlying file descriptor, and put the...">readRaw</a>(&amp;temp, <span class="keyword">sizeof</span>(uint32_t), timeout)) {
554
+ <a name="l00532"></a>00532 <span class="keywordflow">return</span> <span class="keyword">false</span>;
555
+ <a name="l00533"></a>00533 } <span class="keywordflow">else</span> {
556
+ <a name="l00534"></a>00534 value = ntohl(temp);
557
+ <a name="l00535"></a>00535 <span class="keywordflow">return</span> <span class="keyword">true</span>;
558
+ <a name="l00536"></a>00536 }
559
+ <a name="l00537"></a>00537 }
560
+ <a name="l00538"></a>00538 <span class="comment"></span>
561
+ <a name="l00539"></a>00539 <span class="comment"> /**</span>
562
+ <a name="l00540"></a>00540 <span class="comment"> * Read a scalar message from the underlying file descriptor.</span>
563
+ <a name="l00541"></a>00541 <span class="comment"> *</span>
564
+ <a name="l00542"></a>00542 <span class="comment"> * @param output The message will be put in here.</span>
565
+ <a name="l00543"></a>00543 <span class="comment"> * @param maxSize The maximum number of bytes that may be read. If the</span>
566
+ <a name="l00544"></a>00544 <span class="comment"> * scalar to read is larger than this, then a SecurityException</span>
567
+ <a name="l00545"></a>00545 <span class="comment"> * will be thrown. Set to 0 for no size limit.</span>
568
+ <a name="l00546"></a>00546 <span class="comment"> * @param timeout A pointer to an integer, representing the maximum number of</span>
569
+ <a name="l00547"></a>00547 <span class="comment"> * milliseconds to spend on reading the entire scalar.</span>
570
+ <a name="l00548"></a>00548 <span class="comment"> * A TimeoutException will be thrown if unable to read the entire</span>
571
+ <a name="l00549"></a>00549 <span class="comment"> * scalar within this time period.</span>
572
+ <a name="l00550"></a>00550 <span class="comment"> * If no exception is thrown, the the amount of time spent on waiting</span>
573
+ <a name="l00551"></a>00551 <span class="comment"> * will be deducted from &lt;tt&gt;*timeout&lt;/tt&gt;.</span>
574
+ <a name="l00552"></a>00552 <span class="comment"> * Pass NULL if you do not want to enforce any time limits.</span>
575
+ <a name="l00553"></a>00553 <span class="comment"> * @returns Whether end-of-file was reached during reading.</span>
576
+ <a name="l00554"></a>00554 <span class="comment"> * @throws SystemException An error occured while reading data from the file descriptor.</span>
577
+ <a name="l00555"></a>00555 <span class="comment"> * @throws SecurityException There is more data to read than allowed by maxSize.</span>
578
+ <a name="l00556"></a>00556 <span class="comment"> * @throws TimeoutException Unable to read the entire scalar within &lt;tt&gt;timeout&lt;/tt&gt;</span>
579
+ <a name="l00557"></a>00557 <span class="comment"> * milliseconds.</span>
580
+ <a name="l00558"></a>00558 <span class="comment"> * @throws boost::thread_interrupted</span>
581
+ <a name="l00559"></a>00559 <span class="comment"> * @see writeScalar()</span>
582
+ <a name="l00560"></a>00560 <span class="comment"> */</span>
583
+ <a name="l00561"></a><a class="code" href="classPassenger_1_1MessageChannel.html#1f3cf672b566166ed920c2bba4d19604">00561</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1MessageChannel.html#1f3cf672b566166ed920c2bba4d19604" title="Read a scalar message from the underlying file descriptor.">readScalar</a>(<span class="keywordtype">string</span> &amp;output, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> maxSize = 0, <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span> *timeout = NULL) {
584
+ <a name="l00562"></a>00562 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> size;
585
+ <a name="l00563"></a>00563 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> remaining;
586
+ <a name="l00564"></a>00564
587
+ <a name="l00565"></a>00565 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1MessageChannel.html#7b0c67852ea8ab455af75b1037c7f8b6" title="Read a 32-bit big-endian unsigned integer from the underlying file descriptor.">readUint32</a>(size, timeout)) {
588
+ <a name="l00566"></a>00566 <span class="keywordflow">return</span> <span class="keyword">false</span>;
589
+ <a name="l00567"></a>00567 }
590
+ <a name="l00568"></a>00568
591
+ <a name="l00569"></a>00569 <span class="keywordflow">if</span> (maxSize != 0 &amp;&amp; size &gt; maxSize) {
592
+ <a name="l00570"></a>00570 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SecurityException.html" title="Represents some kind of security error.">SecurityException</a>(<span class="stringliteral">"There is more data available than is allowed by the size limit."</span>);
593
+ <a name="l00571"></a>00571 }
594
+ <a name="l00572"></a>00572
595
+ <a name="l00573"></a>00573 output.clear();
596
+ <a name="l00574"></a>00574 output.reserve(size);
597
+ <a name="l00575"></a>00575 remaining = size;
598
+ <a name="l00576"></a>00576 <span class="keywordflow">if</span> (OXT_LIKELY(remaining &gt; 0)) {
599
+ <a name="l00577"></a>00577 <span class="keywordtype">char</span> buf[1024 * 32];
600
+ <a name="l00578"></a>00578 <span class="comment">// Wipe the buffer when we're done; it might contain sensitive data.</span>
601
+ <a name="l00579"></a>00579 <a class="code" href="classPassenger_1_1MemZeroGuard.html" title="Fills the given memory space or string with zeroes when a MemoryZeroGuard object...">MemZeroGuard</a> g(buf, <span class="keyword">sizeof</span>(buf));
602
+ <a name="l00580"></a>00580
603
+ <a name="l00581"></a>00581 <span class="keywordflow">while</span> (remaining &gt; 0) {
604
+ <a name="l00582"></a>00582 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> blockSize = min((<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>) <span class="keyword">sizeof</span>(buf), remaining);
605
+ <a name="l00583"></a>00583
606
+ <a name="l00584"></a>00584 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1MessageChannel.html#b471dc1888f030e20ed23068a160ec2a" title="Read exactly size bytes of data from the underlying file descriptor, and put the...">readRaw</a>(buf, blockSize, timeout)) {
607
+ <a name="l00585"></a>00585 <span class="keywordflow">return</span> <span class="keyword">false</span>;
608
+ <a name="l00586"></a>00586 }
609
+ <a name="l00587"></a>00587 output.append(buf, blockSize);
610
+ <a name="l00588"></a>00588 remaining -= blockSize;
611
+ <a name="l00589"></a>00589 }
612
+ <a name="l00590"></a>00590 }
613
+ <a name="l00591"></a>00591 <span class="keywordflow">return</span> <span class="keyword">true</span>;
614
+ <a name="l00592"></a>00592 }
615
+ <a name="l00593"></a>00593 <span class="comment"></span>
616
+ <a name="l00594"></a>00594 <span class="comment"> /**</span>
617
+ <a name="l00595"></a>00595 <span class="comment"> * Read exactly &lt;tt&gt;size&lt;/tt&gt; bytes of data from the underlying file descriptor,</span>
618
+ <a name="l00596"></a>00596 <span class="comment"> * and put the result in &lt;tt&gt;buf&lt;/tt&gt;. If end-of-file has been reached, or if</span>
619
+ <a name="l00597"></a>00597 <span class="comment"> * end-of-file was encountered before &lt;tt&gt;size&lt;/tt&gt; bytes have been read, then</span>
620
+ <a name="l00598"></a>00598 <span class="comment"> * &lt;tt&gt;false&lt;/tt&gt; will be returned. Otherwise (i.e. if the read was successful),</span>
621
+ <a name="l00599"></a>00599 <span class="comment"> * &lt;tt&gt;true&lt;/tt&gt; will be returned.</span>
622
+ <a name="l00600"></a>00600 <span class="comment"> *</span>
623
+ <a name="l00601"></a>00601 <span class="comment"> * @param buf The buffer to place the read data in. This buffer must be at least</span>
624
+ <a name="l00602"></a>00602 <span class="comment"> * &lt;tt&gt;size&lt;/tt&gt; bytes long.</span>
625
+ <a name="l00603"></a>00603 <span class="comment"> * @param size The number of bytes to read.</span>
626
+ <a name="l00604"></a>00604 <span class="comment"> * @param timeout A pointer to an integer, which specifies the maximum number of</span>
627
+ <a name="l00605"></a>00605 <span class="comment"> * milliseconds that may be spent on reading the &lt;tt&gt;size&lt;/tt&gt; bytes</span>
628
+ <a name="l00606"></a>00606 <span class="comment"> * of data. If the timeout expired then TimeoutException will be</span>
629
+ <a name="l00607"></a>00607 <span class="comment"> * thrown.</span>
630
+ <a name="l00608"></a>00608 <span class="comment"> * If this function returns without throwing an exception, then the</span>
631
+ <a name="l00609"></a>00609 <span class="comment"> * total number of milliseconds spent on reading will be deducted</span>
632
+ <a name="l00610"></a>00610 <span class="comment"> * from &lt;tt&gt;timeout&lt;/tt&gt;.</span>
633
+ <a name="l00611"></a>00611 <span class="comment"> * Pass NULL if you do not want to enforce a timeout.</span>
634
+ <a name="l00612"></a>00612 <span class="comment"> * @return Whether reading was successful or whether EOF was reached.</span>
635
+ <a name="l00613"></a>00613 <span class="comment"> * @pre buf != NULL</span>
636
+ <a name="l00614"></a>00614 <span class="comment"> * @throws SystemException Something went wrong during reading.</span>
637
+ <a name="l00615"></a>00615 <span class="comment"> * @throws TimeoutException Unable to read &lt;tt&gt;size&lt;/tt&gt; bytes of data within</span>
638
+ <a name="l00616"></a>00616 <span class="comment"> * &lt;tt&gt;timeout&lt;/tt&gt; milliseconds.</span>
639
+ <a name="l00617"></a>00617 <span class="comment"> * @throws boost::thread_interrupted</span>
640
+ <a name="l00618"></a>00618 <span class="comment"> * @see writeRaw()</span>
641
+ <a name="l00619"></a>00619 <span class="comment"> */</span>
642
+ <a name="l00620"></a><a class="code" href="classPassenger_1_1MessageChannel.html#b471dc1888f030e20ed23068a160ec2a">00620</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1MessageChannel.html#b471dc1888f030e20ed23068a160ec2a" title="Read exactly size bytes of data from the underlying file descriptor, and put the...">readRaw</a>(<span class="keywordtype">void</span> *buf, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> size, <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span> *timeout = NULL) {
643
+ <a name="l00621"></a>00621 ssize_t ret;
644
+ <a name="l00622"></a>00622 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> alreadyRead = 0;
645
+ <a name="l00623"></a>00623
646
+ <a name="l00624"></a>00624 <span class="keywordflow">while</span> (alreadyRead &lt; size) {
647
+ <a name="l00625"></a>00625 <span class="keywordflow">if</span> (timeout != NULL &amp;&amp; !<a class="code" href="classPassenger_1_1MessageChannel.html#c2407ed109785b49794989507c570149" title="Waits at most *timeout milliseconds for the file descriptor to become readable.">waitUntilReadable</a>(timeout)) {
648
+ <a name="l00626"></a>00626 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1TimeoutException.html" title="An exception indicating that some timeout expired.">TimeoutException</a>(<span class="stringliteral">"Cannot read enough data within the specified timeout."</span>);
649
+ <a name="l00627"></a>00627 }
650
+ <a name="l00628"></a>00628 ret = <a class="code" href="classPassenger_1_1MessageChannel.html#129659b60d1a663337873d2af944431e" title="Read an array message from the underlying file descriptor.">syscalls::read</a>(fd, (<span class="keywordtype">char</span> *) buf + alreadyRead, size - alreadyRead);
651
+ <a name="l00629"></a>00629 <span class="keywordflow">if</span> (ret == -1) {
652
+ <a name="l00630"></a>00630 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"read() failed"</span>, errno);
653
+ <a name="l00631"></a>00631 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (ret == 0) {
654
+ <a name="l00632"></a>00632 <span class="keywordflow">return</span> <span class="keyword">false</span>;
655
+ <a name="l00633"></a>00633 } <span class="keywordflow">else</span> {
656
+ <a name="l00634"></a>00634 alreadyRead += ret;
657
+ <a name="l00635"></a>00635 }
658
+ <a name="l00636"></a>00636 }
659
+ <a name="l00637"></a>00637 <span class="keywordflow">return</span> <span class="keyword">true</span>;
660
+ <a name="l00638"></a>00638 }
661
+ <a name="l00639"></a>00639 <span class="comment"></span>
662
+ <a name="l00640"></a>00640 <span class="comment"> /**</span>
663
+ <a name="l00641"></a>00641 <span class="comment"> * Waits at most &lt;tt&gt;*timeout&lt;/tt&gt; milliseconds for the file descriptor to become readable.</span>
664
+ <a name="l00642"></a>00642 <span class="comment"> * Returns true if it become readable within the timeout, false if the timeout expired.</span>
665
+ <a name="l00643"></a>00643 <span class="comment"> *</span>
666
+ <a name="l00644"></a>00644 <span class="comment"> * &lt;tt&gt;*timeout&lt;/tt&gt; may be 0, in which case this method will check whether the file</span>
667
+ <a name="l00645"></a>00645 <span class="comment"> * descriptor is readable, and immediately returns without waiting.</span>
668
+ <a name="l00646"></a>00646 <span class="comment"> *</span>
669
+ <a name="l00647"></a>00647 <span class="comment"> * If no exception is thrown, this method deducts the number of milliseconds that has</span>
670
+ <a name="l00648"></a>00648 <span class="comment"> * passed from &lt;tt&gt;*timeout&lt;/tt&gt;.</span>
671
+ <a name="l00649"></a>00649 <span class="comment"> *</span>
672
+ <a name="l00650"></a>00650 <span class="comment"> * @throws SystemException</span>
673
+ <a name="l00651"></a>00651 <span class="comment"> * @throws boost::thread_interrupted</span>
674
+ <a name="l00652"></a>00652 <span class="comment"> */</span>
675
+ <a name="l00653"></a><a class="code" href="classPassenger_1_1MessageChannel.html#c2407ed109785b49794989507c570149">00653</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1MessageChannel.html#c2407ed109785b49794989507c570149" title="Waits at most *timeout milliseconds for the file descriptor to become readable.">waitUntilReadable</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span> *timeout) {
676
+ <a name="l00654"></a>00654 fd_set fds;
677
+ <a name="l00655"></a>00655 <span class="keyword">struct </span>timeval tv;
678
+ <a name="l00656"></a>00656 <span class="keywordtype">int</span> ret;
679
+ <a name="l00657"></a>00657
680
+ <a name="l00658"></a>00658 FD_ZERO(&amp;fds);
681
+ <a name="l00659"></a>00659 FD_SET(fd, &amp;fds);
682
+ <a name="l00660"></a>00660 tv.tv_sec = *timeout / 1000;
683
+ <a name="l00661"></a>00661 tv.tv_usec = *timeout % 1000 * 1000;
684
+ <a name="l00662"></a>00662
685
+ <a name="l00663"></a>00663 Timer timer;
686
+ <a name="l00664"></a>00664 ret = syscalls::select(fd + 1, &amp;fds, NULL, NULL, &amp;tv);
687
+ <a name="l00665"></a>00665 <span class="keywordflow">if</span> (ret == -1) {
688
+ <a name="l00666"></a>00666 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"select() failed"</span>, errno);
689
+ <a name="l00667"></a>00667 } <span class="keywordflow">else</span> {
690
+ <a name="l00668"></a>00668 <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span> elapsed = timer.elapsed();
691
+ <a name="l00669"></a>00669 <span class="keywordflow">if</span> (elapsed &gt; *timeout) {
692
+ <a name="l00670"></a>00670 *timeout = 0;
693
+ <a name="l00671"></a>00671 } <span class="keywordflow">else</span> {
694
+ <a name="l00672"></a>00672 *timeout -= elapsed;
695
+ <a name="l00673"></a>00673 }
696
+ <a name="l00674"></a>00674 <span class="keywordflow">return</span> ret != 0;
697
+ <a name="l00675"></a>00675 }
698
+ <a name="l00676"></a>00676 }
699
+ <a name="l00677"></a>00677 <span class="comment"></span>
700
+ <a name="l00678"></a>00678 <span class="comment"> /**</span>
701
+ <a name="l00679"></a>00679 <span class="comment"> * Receive a file descriptor, which had been passed over the underlying</span>
702
+ <a name="l00680"></a>00680 <span class="comment"> * file descriptor.</span>
703
+ <a name="l00681"></a>00681 <span class="comment"> *</span>
704
+ <a name="l00682"></a>00682 <span class="comment"> * @param negotiate See Ruby's MessageChannel#send_io method's comments.</span>
705
+ <a name="l00683"></a>00683 <span class="comment"> * @return The passed file descriptor.</span>
706
+ <a name="l00684"></a>00684 <span class="comment"> * @throws SystemException If something went wrong during the</span>
707
+ <a name="l00685"></a>00685 <span class="comment"> * receiving of a file descriptor. Perhaps the underlying</span>
708
+ <a name="l00686"></a>00686 <span class="comment"> * file descriptor isn't a Unix socket.</span>
709
+ <a name="l00687"></a>00687 <span class="comment"> * @throws IOException Whatever was received doesn't seem to be a</span>
710
+ <a name="l00688"></a>00688 <span class="comment"> * file descriptor.</span>
711
+ <a name="l00689"></a>00689 <span class="comment"> * @throws boost::thread_interrupted</span>
712
+ <a name="l00690"></a>00690 <span class="comment"> */</span>
713
+ <a name="l00691"></a><a class="code" href="classPassenger_1_1MessageChannel.html#1a28ba9d078f38f2831673092ac9dcbc">00691</a> <span class="keywordtype">int</span> <a class="code" href="classPassenger_1_1MessageChannel.html#1a28ba9d078f38f2831673092ac9dcbc" title="Receive a file descriptor, which had been passed over the underlying file descriptor...">readFileDescriptor</a>(<span class="keywordtype">bool</span> negotiate = <span class="keyword">true</span>) {
714
+ <a name="l00692"></a>00692 <span class="comment">// See message_channel.rb for more info about negotiation.</span>
715
+ <a name="l00693"></a>00693 <span class="keywordflow">if</span> (negotiate) {
716
+ <a name="l00694"></a>00694 <a class="code" href="classPassenger_1_1MessageChannel.html#150f68bc47e060dcc6ca35bee047914d" title="Send an array message, which consists of the given elements, over the underlying...">write</a>(<span class="stringliteral">"pass IO"</span>, NULL);
717
+ <a name="l00695"></a>00695 }
718
+ <a name="l00696"></a>00696
719
+ <a name="l00697"></a>00697 <span class="keyword">struct </span>msghdr msg;
720
+ <a name="l00698"></a>00698 <span class="keyword">struct </span>iovec vec;
721
+ <a name="l00699"></a>00699 <span class="keywordtype">char</span> dummy[1];
722
+ <a name="l00700"></a>00700 <span class="preprocessor"> #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)</span>
723
+ <a name="l00701"></a>00701 <span class="preprocessor"></span> <span class="comment">// File descriptor passing macros (CMSG_*) seem to be broken</span>
724
+ <a name="l00702"></a>00702 <span class="comment">// on 64-bit MacOS X. This structure works around the problem.</span>
725
+ <a name="l00703"></a>00703 <span class="keyword">struct </span>{
726
+ <a name="l00704"></a>00704 <span class="keyword">struct </span>cmsghdr header;
727
+ <a name="l00705"></a>00705 <span class="keywordtype">int</span> fd;
728
+ <a name="l00706"></a>00706 } control_data;
729
+ <a name="l00707"></a>00707 <span class="preprocessor"> #define EXPECTED_CMSG_LEN sizeof(control_data)</span>
730
+ <a name="l00708"></a>00708 <span class="preprocessor"></span><span class="preprocessor"> #else</span>
731
+ <a name="l00709"></a>00709 <span class="preprocessor"></span> <span class="keywordtype">char</span> control_data[CMSG_SPACE(<span class="keyword">sizeof</span>(<span class="keywordtype">int</span>))];
732
+ <a name="l00710"></a>00710 <span class="preprocessor"> #define EXPECTED_CMSG_LEN CMSG_LEN(sizeof(int))</span>
733
+ <a name="l00711"></a>00711 <span class="preprocessor"></span><span class="preprocessor"> #endif</span>
734
+ <a name="l00712"></a>00712 <span class="preprocessor"></span> <span class="keyword">struct </span>cmsghdr *control_header;
735
+ <a name="l00713"></a>00713 <span class="keywordtype">int</span> ret;
736
+ <a name="l00714"></a>00714
737
+ <a name="l00715"></a>00715 msg.msg_name = NULL;
738
+ <a name="l00716"></a>00716 msg.msg_namelen = 0;
739
+ <a name="l00717"></a>00717
740
+ <a name="l00718"></a>00718 dummy[0] = <span class="charliteral">'\0'</span>;
741
+ <a name="l00719"></a>00719 vec.iov_base = dummy;
742
+ <a name="l00720"></a>00720 vec.iov_len = <span class="keyword">sizeof</span>(dummy);
743
+ <a name="l00721"></a>00721 msg.msg_iov = &amp;vec;
744
+ <a name="l00722"></a>00722 msg.msg_iovlen = 1;
745
+ <a name="l00723"></a>00723
746
+ <a name="l00724"></a>00724 msg.msg_control = (caddr_t) &amp;control_data;
747
+ <a name="l00725"></a>00725 msg.msg_controllen = <span class="keyword">sizeof</span>(control_data);
748
+ <a name="l00726"></a>00726 msg.msg_flags = 0;
749
+ <a name="l00727"></a>00727
750
+ <a name="l00728"></a>00728 ret = syscalls::recvmsg(fd, &amp;msg, 0);
751
+ <a name="l00729"></a>00729 <span class="keywordflow">if</span> (ret == -1) {
752
+ <a name="l00730"></a>00730 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot read file descriptor with recvmsg()"</span>, errno);
753
+ <a name="l00731"></a>00731 }
754
+ <a name="l00732"></a>00732
755
+ <a name="l00733"></a>00733 control_header = CMSG_FIRSTHDR(&amp;msg);
756
+ <a name="l00734"></a>00734 <span class="keywordflow">if</span> (control_header == NULL) {
757
+ <a name="l00735"></a>00735 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"No valid file descriptor received."</span>);
758
+ <a name="l00736"></a>00736 }
759
+ <a name="l00737"></a>00737 <span class="keywordflow">if</span> (control_header-&gt;cmsg_len != EXPECTED_CMSG_LEN
760
+ <a name="l00738"></a>00738 || control_header-&gt;cmsg_level != SOL_SOCKET
761
+ <a name="l00739"></a>00739 || control_header-&gt;cmsg_type != SCM_RIGHTS) {
762
+ <a name="l00740"></a>00740 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1IOException.html" title="Represents an error that occured during an I/O operation.">IOException</a>(<span class="stringliteral">"No valid file descriptor received."</span>);
763
+ <a name="l00741"></a>00741 }
764
+ <a name="l00742"></a>00742
765
+ <a name="l00743"></a>00743 <span class="preprocessor"> #if defined(__APPLE__) || defined(__SOLARIS__) || defined(__arm__)</span>
766
+ <a name="l00744"></a>00744 <span class="preprocessor"></span> <span class="keywordtype">int</span> fd = control_data.fd;
767
+ <a name="l00745"></a>00745 <span class="preprocessor"> #else</span>
768
+ <a name="l00746"></a>00746 <span class="preprocessor"></span> <span class="keywordtype">int</span> fd = *((<span class="keywordtype">int</span> *) CMSG_DATA(control_header));
769
+ <a name="l00747"></a>00747 <span class="preprocessor"> #endif</span>
770
+ <a name="l00748"></a>00748 <span class="preprocessor"></span>
771
+ <a name="l00749"></a>00749 <span class="keywordflow">if</span> (negotiate) {
772
+ <a name="l00750"></a>00750 <span class="keywordflow">try</span> {
773
+ <a name="l00751"></a>00751 <a class="code" href="classPassenger_1_1MessageChannel.html#150f68bc47e060dcc6ca35bee047914d" title="Send an array message, which consists of the given elements, over the underlying...">write</a>(<span class="stringliteral">"got IO"</span>, NULL);
774
+ <a name="l00752"></a>00752 } <span class="keywordflow">catch</span> (...) {
775
+ <a name="l00753"></a>00753 this_thread::disable_syscall_interruption dsi;
776
+ <a name="l00754"></a>00754 <a class="code" href="classPassenger_1_1MessageChannel.html#06309e208fc5e10642a2e9bbe0f351eb" title="Close the underlying file descriptor.">syscalls::close</a>(fd);
777
+ <a name="l00755"></a>00755 <span class="keywordflow">throw</span>;
778
+ <a name="l00756"></a>00756 }
779
+ <a name="l00757"></a>00757 }
780
+ <a name="l00758"></a>00758
781
+ <a name="l00759"></a>00759 <span class="keywordflow">return</span> fd;
782
+ <a name="l00760"></a>00760 }
783
+ <a name="l00761"></a>00761 <span class="comment"></span>
784
+ <a name="l00762"></a>00762 <span class="comment"> /**</span>
785
+ <a name="l00763"></a>00763 <span class="comment"> * Set the timeout value for reading data from this channel.</span>
786
+ <a name="l00764"></a>00764 <span class="comment"> * If no data can be read within the timeout period, then a</span>
787
+ <a name="l00765"></a>00765 <span class="comment"> * SystemException will be thrown by one of the read methods,</span>
788
+ <a name="l00766"></a>00766 <span class="comment"> * with error code EAGAIN or EWOULDBLOCK.</span>
789
+ <a name="l00767"></a>00767 <span class="comment"> *</span>
790
+ <a name="l00768"></a>00768 <span class="comment"> * @param msec The timeout, in milliseconds. If 0 is given,</span>
791
+ <a name="l00769"></a>00769 <span class="comment"> * there will be no timeout.</span>
792
+ <a name="l00770"></a>00770 <span class="comment"> * @throws SystemException Cannot set the timeout.</span>
793
+ <a name="l00771"></a>00771 <span class="comment"> */</span>
794
+ <a name="l00772"></a><a class="code" href="classPassenger_1_1MessageChannel.html#eb69bffbbb148c9bc8662e20b416c4e2">00772</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1MessageChannel.html#eb69bffbbb148c9bc8662e20b416c4e2" title="Set the timeout value for reading data from this channel.">setReadTimeout</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> msec) {
795
+ <a name="l00773"></a>00773 <span class="comment">// See the comment for setWriteTimeout().</span>
796
+ <a name="l00774"></a>00774 <span class="keyword">struct </span>timeval tv;
797
+ <a name="l00775"></a>00775 <span class="keywordtype">int</span> ret;
798
+ <a name="l00776"></a>00776
799
+ <a name="l00777"></a>00777 tv.tv_sec = msec / 1000;
800
+ <a name="l00778"></a>00778 tv.tv_usec = msec % 1000 * 1000;
801
+ <a name="l00779"></a>00779 ret = syscalls::setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
802
+ <a name="l00780"></a>00780 &amp;tv, <span class="keyword">sizeof</span>(tv));
803
+ <a name="l00781"></a>00781 <span class="preprocessor"> #ifndef __SOLARIS__</span>
804
+ <a name="l00782"></a>00782 <span class="preprocessor"></span> <span class="comment">// SO_RCVTIMEO is unimplemented and returns an error on Solaris</span>
805
+ <a name="l00783"></a>00783 <span class="comment">// 9 and 10 SPARC. Seems to work okay without it.</span>
806
+ <a name="l00784"></a>00784 <span class="keywordflow">if</span> (ret == -1) {
807
+ <a name="l00785"></a>00785 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot set read timeout for socket"</span>, errno);
808
+ <a name="l00786"></a>00786 }
809
+ <a name="l00787"></a>00787 <span class="preprocessor"> #endif</span>
810
+ <a name="l00788"></a>00788 <span class="preprocessor"></span> }
811
+ <a name="l00789"></a>00789 <span class="comment"></span>
812
+ <a name="l00790"></a>00790 <span class="comment"> /**</span>
813
+ <a name="l00791"></a>00791 <span class="comment"> * Set the timeout value for writing data to this channel.</span>
814
+ <a name="l00792"></a>00792 <span class="comment"> * If no data can be written within the timeout period, then a</span>
815
+ <a name="l00793"></a>00793 <span class="comment"> * SystemException will be thrown, with error code EAGAIN or</span>
816
+ <a name="l00794"></a>00794 <span class="comment"> * EWOULDBLOCK.</span>
817
+ <a name="l00795"></a>00795 <span class="comment"> *</span>
818
+ <a name="l00796"></a>00796 <span class="comment"> * @param msec The timeout, in milliseconds. If 0 is given,</span>
819
+ <a name="l00797"></a>00797 <span class="comment"> * there will be no timeout.</span>
820
+ <a name="l00798"></a>00798 <span class="comment"> * @throws SystemException Cannot set the timeout.</span>
821
+ <a name="l00799"></a>00799 <span class="comment"> */</span>
822
+ <a name="l00800"></a><a class="code" href="classPassenger_1_1MessageChannel.html#77c5d7c47f387cf43992ebeb14e3c6c7">00800</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1MessageChannel.html#77c5d7c47f387cf43992ebeb14e3c6c7" title="Set the timeout value for writing data to this channel.">setWriteTimeout</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> msec) {
823
+ <a name="l00801"></a>00801 <span class="comment">// People say that SO_RCVTIMEO/SO_SNDTIMEO are unreliable and</span>
824
+ <a name="l00802"></a>00802 <span class="comment">// not well-implemented on all platforms.</span>
825
+ <a name="l00803"></a>00803 <span class="comment">// http://www.developerweb.net/forum/archive/index.php/t-3439.html</span>
826
+ <a name="l00804"></a>00804 <span class="comment">// That's why we use APR's timeout facilities as well (see Hooks.cpp).</span>
827
+ <a name="l00805"></a>00805 <span class="keyword">struct </span>timeval tv;
828
+ <a name="l00806"></a>00806 <span class="keywordtype">int</span> ret;
829
+ <a name="l00807"></a>00807
830
+ <a name="l00808"></a>00808 tv.tv_sec = msec / 1000;
831
+ <a name="l00809"></a>00809 tv.tv_usec = msec % 1000 * 1000;
832
+ <a name="l00810"></a>00810 ret = syscalls::setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
833
+ <a name="l00811"></a>00811 &amp;tv, <span class="keyword">sizeof</span>(tv));
834
+ <a name="l00812"></a>00812 <span class="preprocessor"> #ifndef __SOLARIS__</span>
835
+ <a name="l00813"></a>00813 <span class="preprocessor"></span> <span class="comment">// SO_SNDTIMEO is unimplemented and returns an error on Solaris</span>
836
+ <a name="l00814"></a>00814 <span class="comment">// 9 and 10 SPARC. Seems to work okay without it.</span>
837
+ <a name="l00815"></a>00815 <span class="keywordflow">if</span> (ret == -1) {
838
+ <a name="l00816"></a>00816 <span class="keywordflow">throw</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a>(<span class="stringliteral">"Cannot set read timeout for socket"</span>, errno);
839
+ <a name="l00817"></a>00817 }
840
+ <a name="l00818"></a>00818 <span class="preprocessor"> #endif</span>
841
+ <a name="l00819"></a>00819 <span class="preprocessor"></span> }
842
+ <a name="l00820"></a>00820 };
843
+ <a name="l00821"></a>00821
844
+ <a name="l00822"></a>00822 } <span class="comment">// namespace Passenger</span>
845
+ <a name="l00823"></a>00823
846
+ <a name="l00824"></a>00824 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_MESSAGE_CHANNEL_H_ */</span>
822
847
  </pre></div></div>
823
- <hr size="1"><address style="text-align: right;"><small>Generated on Sun Feb 21 12:22:45 2010 for Passenger by&nbsp;
848
+ <hr size="1"><address style="text-align: right;"><small>Generated on Sun Mar 28 14:11:56 2010 for Passenger by&nbsp;
824
849
  <a href="http://www.doxygen.org/index.html">
825
850
  <img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.8 </small></address>
826
851
  </body>