public
Description: Phusion Passenger (mod_rails)
Homepage: http://www.modrails.com/
Clone URL: git://github.com/FooBarWidget/passenger.git
Search Repo:
Click here to lend your support to: passenger and make a donation at www.pledgie.com !
Make shutting down the ApplicationPoolServer daemon and the cleanup of the 
status report FIFO more reliable.
Hongli Lai (Phusion) (author)
Thu May 15 04:51:58 -0700 2008
commit  fc830d5ca01c39f615d2d30117aa546fca422b91
tree    dda1d8955f1bb5929dfd29bf936f54493851a84c
parent  edf8e3ccf07c302498a4f72fa7110d4a144a15b1
...
22
23
24
 
25
26
 
27
 
28
29
30
...
338
339
340
 
341
342
343
...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
392
393
394
...
399
400
401
 
 
 
 
402
403
404
...
420
421
422
 
 
423
424
425
...
441
442
443
 
444
445
446
...
457
458
459
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
460
461
462
...
22
23
24
25
26
27
28
29
30
31
32
33
...
341
342
343
344
345
346
347
...
378
379
380
 
 
 
 
 
 
 
 
 
 
381
382
383
 
 
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
...
408
409
410
411
412
413
414
415
416
417
...
433
434
435
436
437
438
439
440
...
456
457
458
459
460
461
462
...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
0
@@ -22,9 +22,12 @@
0
 #include <boost/thread/mutex.hpp>
0
 
0
 #include <sys/types.h>
0
+#include <sys/stat.h>
0
 #include <sys/wait.h>
0
 #include <sys/socket.h>
0
+#include <cstdio>
0
 #include <cstdlib>
0
+#include <limits.h>
0
 #include <errno.h>
0
 #include <unistd.h>
0
 #include <signal.h>
0
@@ -338,6 +341,7 @@ private:
0
   string m_logFile;
0
   string m_rubyCommand;
0
   string m_user;
0
+ string statusReportFIFO;
0
   
0
   /**
0
    * The PID of the ApplicationPool server process. If no server process
0
@@ -374,21 +378,26 @@ private:
0
       ret = close(serverSocket);
0
     } while (ret == -1 && errno == EINTR);
0
     
0
- /*
0
- * Some Apache modules fork(), but don't close file descriptors.
0
- * mod_wsgi is one such example. Because of that, closing serverSocket
0
- * won't cause the ApplicationPool server to exit. So we send it a
0
- * signal.
0
- */
0
- do {
0
- ret = kill(serverPid, SIGINT);
0
- } while (ret == -1 && errno == EINTR);
0
-
0
     P_DEBUG("Waiting for existing ApplicationPoolServerExecutable to exit...");
0
     begin = time(NULL);
0
     while (!done && time(NULL) < begin + 5) {
0
- done = waitpid(serverPid, NULL, WNOHANG) > 0;
0
- usleep(100000);
0
+ /*
0
+ * Some Apache modules fork(), but don't close file descriptors.
0
+ * mod_wsgi is one such example. Because of that, closing serverSocket
0
+ * won't cause the ApplicationPool server to exit. So we send it a
0
+ * signal.
0
+ */
0
+ do {
0
+ ret = kill(serverPid, SIGINT);
0
+ } while (ret == -1 && errno == EINTR);
0
+
0
+ do {
0
+ ret = waitpid(serverPid, NULL, WNOHANG);
0
+ } while (ret == -1 && errno == EINTR);
0
+ done = ret > 0 || ret == -1;
0
+ if (!done) {
0
+ usleep(100000);
0
+ }
0
     }
0
     if (done) {
0
       P_DEBUG("ApplicationPoolServerExecutable exited.");
0
@@ -399,6 +408,10 @@ private:
0
     }
0
     serverSocket = -1;
0
     serverPid = 0;
0
+
0
+ if (!statusReportFIFO.empty()) {
0
+ unlink(statusReportFIFO.c_str());
0
+ }
0
   }
0
   
0
   /**
0
@@ -420,6 +433,8 @@ private:
0
       throw SystemException("Cannot create a Unix socket pair", errno);
0
     }
0
     
0
+ createStatusReportFIFO();
0
+
0
     pid = fork();
0
     if (pid == 0) { // Child process.
0
       dup2(fds[0], SERVER_SOCKET_FD);
0
@@ -441,6 +456,7 @@ private:
0
         m_logFile.c_str(),
0
         m_rubyCommand.c_str(),
0
         m_user.c_str(),
0
+ statusReportFIFO.c_str(),
0
         NULL);
0
       int e = errno;
0
       fprintf(stderr, "*** Passenger ERROR: Cannot execute %s: %s (%d)\n",
0
@@ -457,6 +473,23 @@ private:
0
       serverPid = pid;
0
     }
0
   }
0
+
0
+ void createStatusReportFIFO() {
0
+ char filename[PATH_MAX];
0
+
0
+ snprintf(filename, sizeof(filename), "/tmp/passenger_status.%d.fifo",
0
+ getpid());
0
+ filename[PATH_MAX - 1] = '\0';
0
+ if (mkfifo(filename, S_IRUSR | S_IWUSR) == -1 && errno != EEXIST) {
0
+ fprintf(stderr, "*** WARNING: Could not create FIFO '%s'; "
0
+ "disabling Passenger ApplicationPool status reporting.\n",
0
+ filename);
0
+ fflush(stderr);
0
+ statusReportFIFO = "";
0
+ } else {
0
+ statusReportFIFO = filename;
0
+ }
0
+ }
0
 
0
 public:
0
   /**
...
38
39
40
41
42
43
44
...
63
64
65
 
 
 
66
67
68
...
80
81
82
83
84
 
 
85
86
87
...
89
90
91
92
93
94
 
 
 
95
96
97
98
99
100
101
102
103
 
 
 
 
 
 
 
104
105
106
...
117
118
119
120
 
 
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
 
137
138
139
...
290
291
292
293
294
 
 
 
 
295
296
297
...
368
369
370
371
 
 
 
 
 
372
373
374
...
383
384
385
 
386
387
388
 
 
389
390
391
392
393
 
394
395
396
...
441
442
443
444
 
445
446
447
...
38
39
40
 
41
42
43
...
62
63
64
65
66
67
68
69
70
...
82
83
84
 
 
85
86
87
88
89
...
91
92
93
 
 
 
94
95
96
97
98
99
100
 
 
 
 
 
101
102
103
104
105
106
107
108
109
110
...
121
122
123
 
124
125
126
127
128
 
 
 
 
 
 
 
 
 
 
 
 
 
129
130
131
132
...
283
284
285
 
 
286
287
288
289
290
291
292
...
363
364
365
 
366
367
368
369
370
371
372
373
...
382
383
384
385
386
 
 
387
388
389
390
391
 
 
392
393
394
395
...
440
441
442
 
443
444
445
446
0
@@ -38,7 +38,6 @@
0
 #include <sys/stat.h>
0
 #include <sys/time.h>
0
 #include <sys/resource.h>
0
-#include <limits.h>
0
 #include <unistd.h>
0
 #include <signal.h>
0
 #include <string>
0
@@ -63,6 +62,9 @@ typedef shared_ptr<Client> ClientPtr;
0
 
0
 #define SERVER_SOCKET_FD 3
0
 
0
+/**
0
+ * Whether we received a signal indicating that we shut gracefully shutdown.
0
+ */
0
 static bool serverDone = false;
0
 
0
 
0
@@ -80,8 +82,8 @@ private:
0
   mutex lock;
0
   string statusReportFIFO;
0
   
0
- void statusReportThread() {
0
- while (true) {
0
+ void statusReportThreadMain() {
0
+ while (!serverDone) {
0
       struct stat buf;
0
       int ret;
0
       
0
@@ -89,18 +91,20 @@ private:
0
         ret = stat(statusReportFIFO.c_str(), &buf);
0
       } while (ret == -1 && errno == EINTR);
0
       if (ret == -1 || !S_ISFIFO(buf.st_mode)) {
0
- // Something bad happened with the status
0
- // report FIFO, so we bail out.
0
- return;
0
+ // Something bad happened with the status report
0
+ // FIFO, so we bail out.
0
+ break;
0
       }
0
       
0
       FILE *f;
0
       
0
- do {
0
- f = fopen(statusReportFIFO.c_str(), "w");
0
- } while (f == NULL && errno == EINTR);
0
- if (f == NULL) {
0
- return;
0
+ if (!serverDone) {
0
+ do {
0
+ f = fopen(statusReportFIFO.c_str(), "w");
0
+ } while (f == NULL && errno == EINTR && !serverDone);
0
+ }
0
+ if (f == NULL || serverDone) {
0
+ break;
0
       }
0
       
0
       string report(pool.toString());
0
@@ -117,23 +121,12 @@ public:
0
    const string &spawnServerCommand,
0
    const string &logFile,
0
    const string &rubyCommand,
0
- const string &user)
0
+ const string &user,
0
+ const string &statusReportFIFO)
0
     : pool(spawnServerCommand, logFile, rubyCommand, user) {
0
     
0
     this->serverSocket = serverSocket;
0
-
0
- char filename[PATH_MAX];
0
- snprintf(filename, sizeof(filename), "/tmp/passenger_status.%d.fifo",
0
- getpid());
0
- filename[PATH_MAX - 1] = '\0';
0
- if (mkfifo(filename, S_IRUSR | S_IWUSR) == -1 && errno != EEXIST) {
0
- fprintf(stderr, "*** WARNING: Could not create FIFO '%s'; "
0
- "disabling Passenger ApplicationPool status reporting.\n",
0
- filename);
0
- fflush(stderr);
0
- } else {
0
- statusReportFIFO = filename;
0
- }
0
+ this->statusReportFIFO = statusReportFIFO;
0
   }
0
   
0
   ~Server() {
0
@@ -290,8 +283,10 @@ private:
0
           break;
0
         }
0
       } catch (const SystemException &e) {
0
- P_WARN("Exception in ApplicationPoolServer client thread during "
0
- "reading of a message: " << e.what());
0
+ if (!serverDone) {
0
+ P_WARN("Exception in ApplicationPoolServer client thread during "
0
+ "reading of a message: " << e.what());
0
+ }
0
         break;
0
       }
0
       
0
@@ -368,7 +363,11 @@ public:
0
   
0
   ~Client() {
0
     if (thr != NULL) {
0
- thr->join();
0
+ // We don't want to wait for the client to close the connection,
0
+ // if we were told to shutdown.
0
+ if (!serverDone) {
0
+ thr->join();
0
+ }
0
       delete thr;
0
     }
0
     close(fd);
0
@@ -383,14 +382,14 @@ gracefulShutdown(int sig) {
0
 
0
 int
0
 Server::start() {
0
+ serverDone = false;
0
   if (!statusReportFIFO.empty()) {
0
- new thread(
0
- bind(&Server::statusReportThread, this),
0
+ thread thr(
0
+ bind(&Server::statusReportThreadMain, this),
0
       1024 * 128
0
     );
0
   }
0
-
0
- serverDone = false;
0
+
0
   signal(SIGINT, gracefulShutdown);
0
   siginterrupt(SIGINT, 1);
0
   
0
@@ -441,7 +440,7 @@ Server::start() {
0
 int
0
 main(int argc, char *argv[]) {
0
   try {
0
- Server server(SERVER_SOCKET_FD, argv[1], argv[2], argv[3], argv[4]);
0
+ Server server(SERVER_SOCKET_FD, argv[1], argv[2], argv[3], argv[4], argv[5]);
0
     return server.start();
0
   } catch (const exception &e) {
0
     fprintf(stderr, "*** An unexpected error occured in the Passenger "

Comments

    No one has commented yet.