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 !
passenger / ext / apache2 / DummySpawnManager.h
100644 92 lines (80 sloc) 2.35 kb
1
2
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#ifndef _PASSENGER_DUMMY_SPAWN_MANAGER_H_
#define _PASSENGER_DUMMY_SPAWN_MANAGER_H_
 
#define DUMMY_REQUEST_HANDLER_EXECUTABLE "/home/hongli/Projects/mod_rails/benchmark/DummyRequestHandler"
 
#include <string>
 
#include <sys/types.h>
#include <sys/wait.h>
#include <cstdio>
#include <unistd.h>
#include <errno.h>
 
#include "Application.h"
#include "Exceptions.h"
 
namespace Passenger {
 
using namespace std;
 
/**
 * This class implements a dummy spawn manager. This spawn manager will spawn
 * benchmark/DummyRequestHandler, which is probably the fastest possible
 * implementation of a request handler. The purpose of this class to benchmark
 * the performance of the Apache module (i.e. not benchmarking the Ruby request
 * handler or Rails itself).
 *
 * This header file is not used by default. Modify ApplicationPool to make use
 * of this file/class.
 *
 * Of course, don't forget to compile benchmark/DummyRequestHandler before you
 * use this class!
 */
class DummySpawnManager {
public:
  ApplicationPtr spawn(const string &appRoot, const string &user = "", const string &group = "") {
    int fd1[2], fd2[2];
    pid_t pid;
    
    if (pipe(fd1) == -1) {
      throw SystemException("Cannot create a pipe", errno);
    }
    if (pipe(fd2) == -1) {
      close(fd1[0]);
      close(fd1[1]);
      throw SystemException("Cannot create a pipe", errno);
    }
    pid = fork();
    if (pid == 0) {
      pid = fork();
      if (pid == 0) {
        dup2(fd1[0], 0);
        dup2(fd2[1], 1);
        close(fd1[0]);
        close(fd1[1]);
        close(fd2[0]);
        close(fd2[1]);
        execlp(DUMMY_REQUEST_HANDLER_EXECUTABLE, DUMMY_REQUEST_HANDLER_EXECUTABLE, NULL);
        int e = errno;
        fprintf(stderr, "Unable to run %s: %s\n", DUMMY_REQUEST_HANDLER_EXECUTABLE, strerror(e));
        fflush(stderr);
        _exit(1);
      } else if (pid == -1) {
        perror("Cannot fork a new process");
        fflush(stderr);
        _exit(1);
      } else {
        _exit(0);
      }
    } else if (pid == -1) {
      close(fd1[0]);
      close(fd1[1]);
      close(fd2[0]);
      close(fd2[1]);
      throw SystemException("Cannot fork a new process", errno);
    } else {
      int reader, writer;
      
      close(fd1[0]);
      close(fd2[1]);
      reader = fd2[0];
      writer = fd1[1];
      waitpid(pid, NULL, 0);
      return ApplicationPtr(new Application(appRoot, pid, reader, writer));
    }
  }
};
 
} // namespace Passenger
 
#endif /* _PASSENGER_DUMMY_SPAWN_MANAGER_H_ */