Ticket #111: omindex-limit-filter-resource-usage.patch
File omindex-limit-filter-resource-usage.patch, 3.8 KB (added by , 17 years ago) |
---|
-
runfilter.cc
19 19 20 20 #include <config.h> 21 21 22 #include <iostream> 22 23 #include <string> 23 24 25 #include <limits.h> 26 #include "safeerrno.h" 24 27 #include <sys/types.h> 25 28 #include <stdio.h> 26 29 #include "safefcntl.h" 30 31 #include <sys/time.h> 32 #include <sys/resource.h> 27 33 #ifdef HAVE_SYS_WAIT_H 28 34 # include <sys/wait.h> 29 35 #endif 36 #include <sys/socket.h> 37 #include "safeunistd.h" 30 38 31 39 #include "runfilter.h" 32 40 … … 50 58 stdout_to_string(const string &cmd) 51 59 { 52 60 string out; 61 #ifdef HAVE_FORK 62 // We want to be able to get the exit status of the child process. 63 signal(SIGCHLD, SIG_DFL); 64 65 int fds[2]; 66 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, fds) < 0) 67 throw ReadError(); 68 69 pid_t child = fork(); 70 if (child == 0) { 71 // We're the child process. 72 73 // Close the parent's side of the socket pair. 74 close(fds[0]); 75 76 // Connect stdout to our side of the socket pair. 77 dup2(fds[1], 1); 78 79 // Limit CPU time to 300 seconds (5 minutes). 80 struct rlimit cpu_limit = { 300, RLIM_INFINITY } ; 81 setrlimit(RLIMIT_CPU, &cpu_limit); 82 83 // Limit process data to 7/8 of free physical memory. 84 static long pagesize = 0; 85 if (pagesize == 0) pagesize = sysconf(_SC_PAGESIZE); 86 87 if (pagesize > 0) { 88 long mem = sysconf(_SC_AVPHYS_PAGES); 89 if (mem > 0) { 90 if (mem >= LONG_MAX / pagesize) { 91 mem = LONG_MAX; 92 } else { 93 mem *= pagesize; 94 } 95 96 mem = (mem / 8) * 7; 97 struct rlimit ram_limit = { mem, RLIM_INFINITY } ; 98 setrlimit(RLIMIT_DATA, &ram_limit); 99 } 100 } 101 102 execl("/bin/sh", "/bin/sh", "-c", cmd.c_str(), (void*)NULL); 103 _exit(-1); 104 } 105 106 // We're the parent process. 107 108 // Close the child's side of the socket pair. 109 close(fds[1]); 110 if (child == -1) { 111 // fork() failed. 112 close(fds[0]); 113 throw ReadError(); 114 } 115 116 int fd = fds[0]; 117 118 while (true) { 119 char buf[4096]; 120 ssize_t res = read(fd, buf, sizeof(buf)); 121 if (res == 0) break; 122 if (res == -1) { 123 if (errno != EINTR) { 124 close(fd); 125 int status; 126 (void)waitpid(child, &status, 0); 127 throw ReadError(); 128 } 129 } 130 out.append(buf, res); 131 } 132 133 close(fd); 134 int status; 135 if (waitpid(child, &status, 0) == -1) { 136 throw ReadError(); 137 } 138 #else 53 139 FILE * fh = popen(cmd.c_str(), "r"); 54 140 if (fh == NULL) throw ReadError(); 55 141 while (!feof(fh)) { … … 62 148 out.append(buf, len); 63 149 } 64 150 int status = pclose(fh); 151 #endif 152 65 153 if (status != 0) { 66 154 if (WIFEXITED(status) && WEXITSTATUS(status) == 127) { 67 155 throw NoSuchFilter(); 68 156 } 157 #ifdef SIGXCPU 158 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGXCPU) { 159 cerr << "Filter process consumed too much CPU time" << endl; 160 } 161 #endif 69 162 throw ReadError(); 70 163 } 71 164 return out; -
configure.ac
74 74 AC_FUNC_STRFTIME 75 75 AC_CHECK_FUNCS(gettimeofday ftime) 76 76 77 dnl See if ftime returns void (as it does on mingw)77 dnl See if ftime() returns void (as it does on mingw). 78 78 if test $ac_cv_func_ftime = yes ; then 79 79 AC_TRY_COMPILE([#include <sys/timeb.h>], 80 80 [struct timeb tp; int i = ftime(&tp);], … … 82 82 AC_DEFINE(FTIME_RETURNS_VOID, 1, [Define if ftime returns void])) 83 83 fi 84 84 85 dnl Check for lstat (not available under mingw for example).85 dnl Check for lstat() (not available under mingw for example). 86 86 AC_CHECK_FUNCS(lstat) 87 87 88 dnl Add in portable replacement for mkdtemp on platforms which lack it. 88 dnl omindex uses fork() under UNIX. 89 AC_CHECK_FUNCS(fork) 90 91 dnl Add in portable replacement for mkdtemp() on platforms which lack it. 89 92 AC_CHECK_FUNCS(mkdtemp) 90 93 AM_CONDITIONAL(NEED_MKDTEMP, [test yes != "$ac_cv_func_mkdtemp"]) 91 94