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 !
- Fix bugs in file descriptor management:
  * Make sure we do not close file descriptors twice. This could have lead 
  to racing conditions, whereby new file descriptors are accidentally 
  closed!
  * Only close file descriptors that are within the valid file descriptor 
  range.
- Add unit test for checking that ApplicationPoolServer does not leak file 
descriptors.
- Valgrind now runs the unit tests with no errors or even warnings!
FooBarWidget (author)
Sun Feb 03 01:27:08 -0800 2008
commit  a3196e06dd1880d72a1c9c36903d80384b7f8ccd
tree    c3c0194ff7241604d9ec88de62869ddb4641718e
parent  ff5e85d3b3d69dd10a2b433fa1c5612867d93497
...
127
128
129
130
131
132
 
133
134
135
...
191
192
193
 
 
 
 
 
 
194
195
196
...
201
202
203
204
205
206
207
...
287
288
289
290
 
 
291
292
293
...
306
307
308
 
309
310
311
...
127
128
129
 
 
 
130
131
132
133
...
189
190
191
192
193
194
195
196
197
198
199
200
...
205
206
207
 
208
209
210
...
290
291
292
 
293
294
295
296
297
...
310
311
312
313
314
315
316
0
@@ -127,9 +127,7 @@
0
       free(pollResult);
0
       // Apparently APR does not always close the file descriptor,
0
       // so we do it manually.
0
- for (set<int>::const_iterator it(fds.begin()); it != fds.end(); it++) {
0
- close(*it);
0
- }
0
+ closeAll();
0
     }
0
   
0
     void add(int fd) {
0
@@ -191,6 +189,12 @@
0
       *fileDescriptors = pollResult;
0
       return num;
0
     }
0
+
0
+ void closeAll() {
0
+ for (set<int>::const_iterator it(fds.begin()); it != fds.end(); it++) {
0
+ close(*it);
0
+ }
0
+ }
0
   };
0
   
0
   StandardApplicationPool pool;
0
@@ -201,7 +205,6 @@
0
   SocketDemultiplexer demultiplexer;
0
   
0
   void threadMain() {
0
- demultiplexer.add(serverSocket);
0
     while (!done) {
0
       int *fds;
0
       unsigned int num;
0
@@ -287,7 +290,8 @@
0
   } */
0
   
0
   void finalize() {
0
- close(serverSocket);
0
+ demultiplexer.closeAll();
0
+ // serverSocket will be closed by demultiplexer.
0
     close(connectSocket);
0
   }
0
   
0
@@ -306,6 +310,7 @@
0
     connectSocket = fds[1];
0
     done = false;
0
     detached = false;
0
+ demultiplexer.add(serverSocket);
0
     thr = new thread(ServerThreadDelegator(this));
0
   }
0
   
...
111
112
113
114
 
115
116
117
...
111
112
113
 
114
115
116
117
0
@@ -111,7 +111,7 @@
0
       close(fds[1]);
0
       
0
       // Close all other file descriptors
0
- for (int i = sysconf(_SC_OPEN_MAX); i >= 0; i--) {
0
+ for (long i = sysconf(_SC_OPEN_MAX) - 1; i >= 0; i--) {
0
         if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO) {
0
           close(i);
0
         }
...
3
4
5
 
6
7
8
9
 
 
 
10
11
12
13
 
 
 
 
14
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
17
18
...
52
53
54
 
 
 
 
 
 
 
55
56
...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
74
75
76
77
78
79
80
81
82
83
84
85
0
@@ -3,16 +3,38 @@
0
 #include "Utils.cpp"
0
 #include <cstring>
0
 #include <unistd.h>
0
+#include <errno.h>
0
 
0
 using namespace Passenger;
0
 
0
 namespace tut {
0
+ static bool firstRun = true;
0
+ static unsigned int initialFileDescriptors;
0
+
0
   struct ApplicationPoolClientServerTest {
0
     ApplicationPoolServerPtr server;
0
     
0
     ApplicationPoolClientServerTest() {
0
+ if (firstRun) {
0
+ initialFileDescriptors = countOpenFileDescriptors();
0
+ firstRun = false;
0
+ }
0
       server = ptr(new ApplicationPoolServer("support/spawn_server_mock.rb"));
0
     }
0
+
0
+ unsigned int countOpenFileDescriptors() {
0
+ int ret;
0
+ unsigned int result = 0;
0
+ for (long i = sysconf(_SC_OPEN_MAX) - 1; i >= 0; i--) {
0
+ do {
0
+ ret = dup2(i, i);
0
+ } while (ret == -1 && errno == EINTR);
0
+ if (ret != -1) {
0
+ result++;
0
+ }
0
+ }
0
+ return result;
0
+ }
0
   };
0
 
0
   DEFINE_TEST_GROUP(ApplicationPoolClientServerTest);
0
@@ -52,6 +74,13 @@
0
     } else {
0
       waitpid(pid, NULL, 0);
0
     }
0
+ }
0
+
0
+ TEST_METHOD(5) {
0
+ // ApplicationPoolServer should not leak file descriptors after running all
0
+ // of the above tests.
0
+ server = ApplicationPoolServerPtr();
0
+ ensure_equals(countOpenFileDescriptors(), initialFileDescriptors);
0
   }
0
 }

Comments

    No one has commented yet.