Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
// run.cc (tested on Mac OS X 10.5/10.6)
#include
#include
#include
#include
#include
#include
#include
#include
#define SLEEP_NSEC 10000 // 0.01s
// smaller value => fine-grained memory monitoring (overhead increases runtime)
struct mach_send_port_msg {
mach_msg_header_t header;
mach_msg_body_t body;
mach_msg_port_descriptor_t task_port;
};
struct mach_recv_port_msg {
mach_send_port_msg m;
mach_msg_trailer_t trailer;
};
static int setup_recv_port (mach_port_t *recv_port) {
mach_port_t port = MACH_PORT_NULL;
if (KERN_SUCCESS !=
mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &port))
std::fprintf (stderr, "mach_port_allocate failed.\n");
if (KERN_SUCCESS !=
mach_port_insert_right (mach_task_self (), port, port, MACH_MSG_TYPE_MAKE_SEND))
std::fprintf (stderr, "mach_port_insert_right failed.\n");
*recv_port = port;
return 0;
}
static int send_port (mach_port_t remote_port, mach_port_t port) {
mach_send_port_msg msg;
msg.header.msgh_remote_port = remote_port;
msg.header.msgh_local_port = MACH_PORT_NULL;
msg.header.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0) |
MACH_MSGH_BITS_COMPLEX;
msg.header.msgh_size = sizeof (msg);
msg.body.msgh_descriptor_count = 1;
msg.task_port.name = port;
msg.task_port.disposition = MACH_MSG_TYPE_COPY_SEND;
msg.task_port.type = MACH_MSG_PORT_DESCRIPTOR;
if (KERN_SUCCESS != mach_msg_send (&msg.header))
std::fprintf (stderr, "mach_msg_send failed.\n");
return 0;
}
static int recv_port (mach_port_t recv_port, mach_port_t *port) {
mach_recv_port_msg msg;
if (KERN_SUCCESS !=
mach_msg (&msg.m.header, MACH_RCV_MSG, 0, sizeof (msg), recv_port,
MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL))
std::fprintf (stderr, "mach_msg failed.\n");
*port = msg.m.task_port.name;
return 0;
}
int main (int argc, char **argv) {
char ** cmd = &argv[1];
struct timeval start, end;
task_t task = MACH_PORT_NULL;
mach_port_t parent_recv_port = MACH_PORT_NULL;
mach_port_t child_recv_port = MACH_PORT_NULL;
// setup port as bootstrap port
if (setup_recv_port (&parent_recv_port) != 0) return -1;
if (KERN_SUCCESS !=
task_set_bootstrap_port (mach_task_self (), parent_recv_port))
std::fprintf (stderr, "task_set_bootstrap_port failed.\n");
// set timer
gettimeofday (&start, 0);
// create new task
pid_t pid = fork ();
if (pid < 0) {
if (KERN_SUCCESS !=
mach_port_deallocate (mach_task_self(), parent_recv_port))
std::fprintf (stderr, "mach_port_deallocate failed.\n");
std::fprintf (stderr, "cannot fork.\n"); std::exit (1);
} else if (pid == 0) { // child process
if (KERN_SUCCESS !=
task_get_bootstrap_port (mach_task_self (), &parent_recv_port))
std::fprintf (stderr, "task_get_bootstrap_port failed.\n");
if (setup_recv_port (&child_recv_port) != 0) return -1;
if (send_port (parent_recv_port, mach_task_self ()) != 0) return -1;
if (send_port (parent_recv_port, child_recv_port) != 0) return -1;
if (recv_port (child_recv_port, &bootstrap_port) != 0) return -1;
if (KERN_SUCCESS
!= task_set_bootstrap_port (mach_task_self (), bootstrap_port))
std::fprintf (stderr, "task_set_bootstrap_port failed.\n");
execvp (cmd[0], cmd);
std::fprintf (stderr, "cannot run %s\n", cmd[0]);
_exit (errno == ENOENT ? 127 : 126);
}
// parent process
std::signal (SIGINT, SIG_IGN);
std::signal (SIGQUIT, SIG_IGN);
if (KERN_SUCCESS !=
task_set_bootstrap_port (mach_task_self (), bootstrap_port))
std::fprintf (stderr, "task_set_bootstrap_port failed.\n");
if (recv_port (parent_recv_port, &task) != 0) return -1;
if (recv_port (parent_recv_port, &child_recv_port) != 0) return -1;
if (send_port (child_recv_port, bootstrap_port) != 0) return -1;
if (KERN_SUCCESS
!= mach_port_deallocate (mach_task_self(), parent_recv_port))
std::fprintf (stderr, "mach_port_deallocate failed.\n");
// monitor memory
size_t mem = 0;
struct task_basic_info t_info;
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
do {
if (KERN_SUCCESS !=
task_info (task, TASK_BASIC_INFO, (task_info_t) &t_info, &t_info_count))
break;
if (mem < t_info.resident_size) mem = t_info.resident_size;
} while (! usleep (SLEEP_NSEC));
// stop timer
int status;
if (waitpid (pid, &status, 0) == -1) //
std::fprintf (stderr, "error waiting for child process.\n");
if ((status & 0xff) == 0x7f)
std::fprintf (stderr, "Command stopped by signal %d\n", (status >> 8) & 0xff);
else if ((status & 0xff) != 0)
std::fprintf (stderr, "Command terminated by signal %d\n", status & 0xff);
else if ((status >> 8) & 0xff)
std::fprintf (stderr, "Command exited with non-zero status %d\n", (status >> 8) & 0xff);
gettimeofday (&end, 0);
std::fprintf (stderr, "elapsed (real): %.3fs; RSS=%.2f MiB (%ld bytes)\n",
end.tv_sec - start.tv_sec + (end.tv_usec - start.tv_usec) * 1e-6,
mem / 1048576.0, mem);
std::signal (SIGINT, SIG_DFL);
std::signal (SIGQUIT, SIG_DFL);
return 0;
}