We got nominated! Help us out and vote for GitHub as Best Bootstrapped Startup of 2008. (You can vote once a day.) [ hide ]

public
Description: Phusion Passenger (mod_rails)
Homepage: http://www.modrails.com/
Clone URL: git://github.com/FooBarWidget/passenger.git
Click here to lend your support to: passenger and make a donation at www.pledgie.com !
Correctly handle exceptions that occur in the ApplicationPoolServer 
threads.
Hongli Lai (Phusion) (author)
Thu Feb 21 12:22:19 -0800 2008
commit  ce3a193bb4865ccfb7489ec7e346161eb05a4fff
tree    db03945d9a2277f0eb0fc22cbc27847f7d27cbf0
parent  02ce854434aa8eecff3d737d09c9c42bfdd8940f
...
183
184
185
186
 
187
188
189
190
 
 
 
191
192
193
...
183
184
185
 
186
187
188
189
 
190
191
192
193
194
195
0
@@ -183,11 +183,13 @@ subdir 'test' do
0
   end
0
   
0
   desc "Run unit tests for the Ruby libraries"
0
- task 'test:ruby' do
0
+ task 'test:ruby' => ['../ext/mod_rails/native_support.so'] do
0
     sh "spec -f s *_spec.rb"
0
   end
0
 
0
- file 'Apache2ModuleTests' => TEST::AP2_OBJECTS.keys + ['../ext/boost/src/libboost_thread.a'] do
0
+ file 'Apache2ModuleTests' => TEST::AP2_OBJECTS.keys +
0
+ ['../ext/boost/src/libboost_thread.a',
0
+ '../ext/mod_rails/native_support.so'] do
0
     objects = TEST::AP2_OBJECTS.keys.join(' ')
0
     create_executable "Apache2ModuleTests", objects,
0
       "#{LDFLAGS} #{APR_LIBS} ../ext/boost/src/libboost_thread.a -lpthread"
...
123
124
125
126
127
128
129
...
217
218
219
220
221
222
223
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
225
226
...
270
271
272
273
274
275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
277
278
...
291
292
293
294
295
296
297
 
 
 
 
 
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
316
 
 
 
317
318
319
...
123
124
125
 
126
127
128
...
216
217
218
 
 
 
 
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
...
279
280
281
 
 
 
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
...
323
324
325
 
 
 
 
326
327
328
329
330
331
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
0
@@ -123,7 +123,6 @@ private:
0
 
0
   /**
0
    * An Application::Session which works together with ApplicationPoolServer.
0
- *
0
    */
0
   class RemoteSession: public Application::Session {
0
   private:
0
@@ -217,10 +216,20 @@ private:
0
       int reader, writer;
0
       
0
       channel.write("get", appRoot.c_str(), user.c_str(), group.c_str(), NULL);
0
- channel.read(args);
0
- reader = channel.readFileDescriptor();
0
- writer = channel.readFileDescriptor();
0
- return ptr(new RemoteSession(data, atoi(args[0].c_str()), reader, writer));
0
+ if (!channel.read(args)) {
0
+ throw IOException("The ApplicationPool server unexpectedly disconnected the connection.");
0
+ }
0
+ if (args[0] == "ok") {
0
+ reader = channel.readFileDescriptor();
0
+ writer = channel.readFileDescriptor();
0
+ return ptr(new RemoteSession(data, atoi(args[1]), reader, writer));
0
+ } else if (args[0] == "SpawnException") {
0
+ throw SpawnException(args[1]);
0
+ } else if (args[0] == "IOException") {
0
+ throw IOException(args[1]);
0
+ } else {
0
+ throw IOException("The ApplicationPool server returned an unknown message.");
0
+ }
0
     }
0
   };
0
   
0
@@ -270,9 +279,32 @@ private:
0
         break;
0
       }
0
       
0
- socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
0
- MessageChannel(serverSocket).writeFileDescriptor(fds[1]);
0
- close(fds[1]);
0
+ // Incoming connect request.
0
+ do {
0
+ ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
0
+ } while (ret == -1 && errno == EINTR);
0
+ if (ret == -1) {
0
+ int e = errno;
0
+ P_ERROR("Cannot create an anonymous Unix socket: " <<
0
+ strerror(e) << " (" << e << ")");
0
+ abort();
0
+
0
+ // Shut up compiler warning.
0
+ bool x = false;
0
+ if (x) {
0
+ printf("%d", e);
0
+ }
0
+ }
0
+
0
+ try {
0
+ MessageChannel(serverSocket).writeFileDescriptor(fds[1]);
0
+ do {
0
+ ret = close(fds[1]);
0
+ } while (ret == -1 && errno == EINTR);
0
+ } catch (const exception &e) {
0
+ P_ERROR("Cannot send a file descriptor: " << e.what());
0
+ abort();
0
+ }
0
       
0
       ClientInfoPtr info(new ClientInfo());
0
       info->fd = fds[0];
0
@@ -291,29 +323,60 @@ private:
0
     map<int, Application::SessionPtr> sessions;
0
     int lastID = 0;
0
 
0
- while (!done) {
0
- if (!channel.read(args)) {
0
- break;
0
- }
0
+ try {
0
+ while (!done) {
0
+ if (!channel.read(args)) {
0
+ break;
0
+ }
0
       
0
- if (args[0] == "get" && args.size() == 4) {
0
- Application::SessionPtr session(pool.get(args[1], args[2], args[3]));
0
- channel.write(toString(lastID).c_str(), NULL);
0
- channel.writeFileDescriptor(session->getReader());
0
- channel.writeFileDescriptor(session->getWriter());
0
- session->closeReader();
0
- session->closeWriter();
0
- sessions[lastID] = session;
0
- lastID++;
0
- } else if (args[0] == "close" && args.size() == 2) {
0
- sessions.erase(atoi(args[1].c_str()));
0
- } else if (args[0] == "setMax") {
0
- pool.setMax(atoi(args[1].c_str()));
0
- } else if (args[0] == "getActive") {
0
- channel.write(toString(pool.getActive()).c_str(), NULL);
0
- } else if (args[0] == "getCount") {
0
- channel.write(toString(pool.getCount()).c_str(), NULL);
0
+ if (args[0] == "get" && args.size() == 4) {
0
+ Application::SessionPtr session;
0
+ try {
0
+ session = pool.get(args[1], args[2], args[3]);
0
+ } catch (const SpawnException &e) {
0
+ channel.write("SpawnException", e.what(), NULL);
0
+ done = true;
0
+ } catch (const IOException &e) {
0
+ channel.write("IOException", e.what(), NULL);
0
+ done = true;
0
+ }
0
+ if (!done) {
0
+ channel.write("ok", toString(lastID).c_str(), NULL);
0
+ channel.writeFileDescriptor(session->getReader());
0
+ channel.writeFileDescriptor(session->getWriter());
0
+ session->closeReader();
0
+ session->closeWriter();
0
+ sessions[lastID] = session;
0
+ lastID++;
0
+ }
0
+
0
+ } else if (args[0] == "close" && args.size() == 2) {
0
+ sessions.erase(atoi(args[1]));
0
+
0
+ } else if (args[0] == "setMax" && args.size() == 2) {
0
+ pool.setMax(atoi(args[1]));
0
+
0
+ } else if (args[0] == "getActive" && args.size() == 1) {
0
+ channel.write(toString(pool.getActive()).c_str(), NULL);
0
+
0
+ } else if (args[0] == "getCount" && args.size() == 1) {
0
+ channel.write(toString(pool.getCount()).c_str(), NULL);
0
+
0
+ } else {
0
+ string name;
0
+ if (args.empty()) {
0
+ name = "(null)";
0
+ } else {
0
+ name = args[0];
0
+ }
0
+ P_WARN("An ApplicationPoolServer client sent an invalid command: "
0
+ << name << " (" << args.size() << " elements)");
0
+ done = true;
0
+ }
0
       }
0
+ } catch (const exception &e) {
0
+ P_WARN("Uncaught exception in ApplicationPoolServer client thread: " <<
0
+ e.what());
0
     }
0
     
0
     mutex::scoped_lock l(lock);
...
1
2
 
3
4
5
...
30
31
32
 
 
 
 
 
33
34
35
...
1
2
3
4
5
6
...
31
32
33
34
35
36
37
38
39
40
41
0
@@ -1,5 +1,6 @@
0
 #include <sys/types.h>
0
 #include <sys/stat.h>
0
+#include <cstdlib>
0
 #include <unistd.h>
0
 #include <fstream>
0
 #include <iostream>
0
@@ -30,6 +31,11 @@ initDebugging(const char *logFile) {
0
   #endif
0
 }
0
 
0
+int
0
+atoi(const string &s) {
0
+ return ::atoi(s.c_str());
0
+}
0
+
0
 void
0
 split(const string &str, char sep, vector<string> &output) {
0
   string::size_type start, pos;
...
51
52
53
 
 
 
 
 
54
55
56
...
87
88
89
 
 
90
91
92
 
 
93
94
95
...
51
52
53
54
55
56
57
58
59
60
61
...
92
93
94
95
96
97
98
99
100
101
102
103
104
0
@@ -51,6 +51,11 @@ toString(T something) {
0
 }
0
 
0
 /**
0
+ * Converts the given string to an integer.
0
+ */
0
+int atoi(const string &s);
0
+
0
+/**
0
  * Split the given string using the given separator.
0
  *
0
  * @param str The string to split.
0
@@ -87,9 +92,13 @@ string findSpawnServer();
0
           expr << std::endl; \
0
       } \
0
     } while (false)
0
+ #define P_WARN P_DEBUG
0
+ #define P_ERROR P_DEBUG
0
   #define P_TRACE P_DEBUG
0
 #else
0
   #define P_DEBUG(expr) do { /* nothing */ } while (false)
0
+ #define P_WARN P_DEBUG
0
+ #define P_ERROR P_DEBUG
0
   #define P_TRACE P_DEBUG
0
 #endif
0
 

Comments

    No one has commented yet.