--- cpulimit-2.6.old/cpulimit.c +++ cpulimit-2.6/cpulimit.c @@ -1,4 +1,4 @@ -/** +/* * This program is licensed under the GNU General Public License, * version 2. A copy of the license can be found in the accompanying * LICENSE file. @@ -97,7 +97,7 @@ //verbose mode int verbose = FALSE; //lazy mode -int lazy = FALSE; +int lazy = TRUE; // is higher priority nice possible? int nice_lim; @@ -119,15 +119,12 @@ "SIGKILL", "SIGTERM", "SIGSTOP", "SIGCONT" }; const int SIGNAL_VALUE[MAX_SIGNAL] = { SIGHUP, SIGINT, SIGQUIT, SIGKILL, SIGTERM, SIGSTOP, SIGCONT }; - - -//return ta-tb in microseconds (no overflow checks!) -inline long timediff(const struct timespec *ta,const struct timespec *tb) { +// return ta-tb in microseconds (no overflow checks!) +static long timediff(const struct timespec *ta,const struct timespec *tb) { unsigned long us = (ta->tv_sec-tb->tv_sec)*1000000 + (ta->tv_nsec/1000 - tb->tv_nsec/1000); return us; } - #ifdef LINUX #include @@ -172,7 +169,7 @@ /* if ( (nice_lim < INT_MAX) && (setpriority(PRIO_PROCESS, my_pid, 19) != 0) ) { - printf("Warning: cannot renice\n"); + fprintf (stderr, "Warning: Can't renice\n"); } */ int i=0; @@ -217,11 +214,11 @@ //no suitable target found if (i++==0) { if (lazy) { - fprintf(stderr,"No process found\n"); + fprintf (stderr,"No process found\n"); exit(2); } else { - fprintf(stderr, "Warning: no target process found. Waiting for it...\n"); + fprintf (stderr, "Warning: No target process found. Waiting for it...\n"); } } @@ -230,15 +227,14 @@ } done: - if (!quiet) - printf("Process %d detected\n",pid); + if (verbose) fprintf (stderr, "Process %d detected\n",pid); //now set high priority, if possible // if (setpriority(PRIO_PROCESS,getpid(),-20)!=0) { /* if ( (nice_lim < INT_MAX) && (setpriority(PRIO_PROCESS, my_pid, nice_lim) != 0) ) { - printf("Warning: cannot renice.\nTo work better you should run this program as root.\n"); + fprintf (stderr, "Warning: Can't renice.\nTo work better you should run this program as root.\n"); } */ return 0; @@ -258,7 +254,7 @@ /* if ( (nice_lim < INT_MAX) && (setpriority(PRIO_PROCESS, my_pid, 19) != 0) ) { - printf("Warning: cannot renice\n"); + fprintf (stderr, "Warning: Cannot renice\n"); } */ char exelink[20]; @@ -292,9 +288,14 @@ } else { //process is the name of the executable file - if (strncmp(exepath+size-strlen(process),process,strlen(process))==0) { - found=1; - } +int x = size - strlen (process); + +if ((x > 0) && + (exepath [x - 1] == '/') && + (strncmp (exepath+x, process, strlen (process)) == 0)) +{ + found = 1; +} } if (found==1) { Check_Us(pid); @@ -323,11 +324,11 @@ //no suitable target found if (i++==0) { if (lazy) { - fprintf(stderr,"No process found\n"); + fprintf (stderr,"No process found\n"); exit(2); } else { - fprintf(stderr, "Warning: no target process found. Waiting for it...\n"); + fprintf (stderr, "Warning: No target process found. Waiting for it...\n"); } } @@ -336,15 +337,14 @@ } done: - if (!quiet) - printf("Process %d detected\n",pid); + if (verbose) fprintf (stderr, "Process %d detected\n",pid); //now set high priority, if possible // if (setpriority(PRIO_PROCESS,getpid(),-20)!=0) { /* if ( (nice_lim < INT_MAX) && (setpriority(PRIO_PROCESS, my_pid, nice_lim) != 0) ) { - printf("Warning: cannot renice.\nTo work better you should run this program as root.\n"); + fprintf (stderr, "Warning: Can't renice.\nTo work better you should run this program as root.\n"); } */ return pid; @@ -362,7 +362,7 @@ sleep(2); // wait for thread clean-up } #endif - printf("Exiting...\n"); + fprintf (stderr, "Exiting...\n"); exit(0); } @@ -529,10 +529,10 @@ } void print_caption() { - printf("\n%%CPU\twork quantum\tsleep quantum\tactive rate\n"); + fprintf (stderr, + "\n%%CPU\twork quantum\tsleep quantum\tactive rate\n"); } - void increase_priority() { //find the best available nice value @@ -795,47 +795,88 @@ #endif // end of monitoring children processes on Linux +void print_usage (FILE *stream,int exit_code) +{ + stream = stdout; + fprintf (stream, +"CPUlimit version %1.1f\n", VERSION); + fprintf (stream, +"Usage: %s TARGET [OPTIONS...] [-- PROGRAM]\n", program_name); + fprintf (stream, +"TARGET must be exactly one of these:\n"); + fprintf (stream, +"-p, --pid=NUMBER Process-ID number\n"); + fprintf (stream, +"-e, --exe=FILE Program file w/o path (needs root privs)\n"); + fprintf (stream, +"-P, --path=PATH Absolute pathname of executable file\n"); + fprintf (stream, +" --exe and --path don't work for scripts\n"); + fprintf (stream, +" Additional rules apply. See: man cpulimit\n"); + fprintf (stream, +"Options:\n"); + fprintf (stream, +"-b --background Run in background\n"); + fprintf (stream, +"-c --cpu=N Override detected number of CPUs\n"); + fprintf (stream, +"-l, --limit=N Max. CPU percentage (required, usually 0 to\n"); + fprintf (stream, +" 100, higher on multi-CPU systems\n"); + fprintf (stream, +"-f --foreground launch target process in foreground and\n"); + fprintf (stream, +" wait for it to exit\n"); +#ifdef LINUX + fprintf (stream, +"-m, --monitor-forks\n"); + fprintf (stream, +" Watch children/forks of target process\n"); +#endif + fprintf (stream, +"-q, --quiet Quiet mode (only print errors)\n"); + fprintf (stream, +"-k, --kill kill processes going over their limit\n"); + fprintf (stream, +" instead of just throttling them.\n"); + fprintf (stream, +"-r, --restore Restore processes after they have\n"); + fprintf (stream, +" been killed. Works with the -k flag.\n"); + fprintf (stream, +"-s, --signal=SIG Send this signal to the watched process when\n"); + fprintf (stream, +" cpulimit exits.\n"); + fprintf (stream, +" Signal should be specified as a number or\n"); + fprintf (stream, +" SIGTERM, SIGCONT, SIGSTOP, etc. SIGCONT is the\n"); + fprintf (stream, +" default.\n"); + fprintf (stream, +"-v, --verbose Opposite of --quiet\n"); + fprintf (stream, +"-z, --lazy Exit if no matching process, or if the pro-\n"); + fprintf (stream, +" cess terminates (default mode)\n"); + fprintf (stream, +"-Z, --notlazy Wait for matching process and loop after\n"); + fprintf (stream, +" process exits (reverse of --lazy)\n"); + fprintf (stream, +" --notlazy doesn't apply if --pid is used\n"); + fprintf (stream, +"-- This is the final CPUlimit option. Following\n"); + fprintf (stream, +" options are for another program to launch.\n"); + fprintf (stream, +"-h, --help Display this screen and exit\n"); -void print_usage(FILE *stream,int exit_code) { - fprintf(stream, "CPUlimit version %1.1f\n", VERSION); - fprintf(stream, "Usage: %s TARGET [OPTIONS...] [-- PROGRAM]\n",program_name); - fprintf(stream, " TARGET must be exactly one of these:\n"); - fprintf(stream, " -p, --pid=N pid of the process\n"); - fprintf(stream, " -e, --exe=FILE name of the executable program file\n"); - fprintf(stream, " The -e option only works when\n"); - fprintf(stream, " cpulimit is run with admin rights.\n"); - fprintf(stream, " -P, --path=PATH absolute path name of the\n"); - fprintf(stream, " executable program file\n"); - fprintf(stream, " OPTIONS\n"); - fprintf(stream, " -b --background run in background\n"); - fprintf(stream, " -f --foreground launch target process in foreground and wait for it to exit\n"); - fprintf(stream, " -c --cpu=N override the detection of CPUs on the machine.\n"); - fprintf(stream, " -l, --limit=N percentage of cpu allowed from 1 up.\n"); - fprintf(stream, " Usually 1 - %d00, but can be higher\n", NCPU); - fprintf(stream, " on multi-core CPUs (mandatory)\n"); - #ifdef LINUX - fprintf(stream, " -m, --monitor-forks Watch children/forks of the target process\n"); - #endif - fprintf(stream, " -q, --quiet run in quiet mode (only print errors).\n"); - fprintf(stream, " -k, --kill kill processes going over their limit\n"); - fprintf(stream, " instead of just throttling them.\n"); - fprintf(stream, " -r, --restore Restore processes after they have\n"); - fprintf(stream, " been killed. Works with the -k flag.\n"); - fprintf(stream, " -s, --signal=SIG Send this signal to the watched process when cpulimit exits.\n"); - fprintf(stream, " Signal should be specificed as a number or \n"); - fprintf(stream, " SIGTERM, SIGCONT, SIGSTOP, etc. SIGCONT is the default.\n"); - fprintf(stream, " -v, --verbose show control statistics\n"); - fprintf(stream, " -z, --lazy exit if there is no suitable target process,\n"); - fprintf(stream, " or if it dies\n"); - fprintf(stream, " -- This is the final CPUlimit option. All following\n"); - fprintf(stream, " options are for another program we will launch.\n"); - fprintf(stream, " -h, --help display this help and exit\n"); - exit(exit_code); + exit (exit_code); } - - // Get the number of CPU cores on this machine. int get_ncpu() { @@ -846,7 +887,6 @@ return ncpu; } - // This function attempts to figure out what signal we should send // target processes based on a command line paramter. First we check // for text such as SIGINT, SIGCONT, SIGSTOP, etc. If no match is found @@ -877,6 +917,8 @@ int main(int argc, char **argv) { + char *cp; + int c; //get program name // char *p=(char*)memrchr(argv[0],(unsigned int)'/',strlen(argv[0])); @@ -903,6 +945,7 @@ { "quiet", no_argument, NULL, 'q' }, { "verbose", no_argument, NULL, 'v' }, { "lazy", no_argument, NULL, 'z' }, + { "notlazy", no_argument, NULL, 'Z' }, { "help", no_argument, NULL, 'h' }, { "cpu", required_argument, NULL, 'c'}, { "signal", required_argument, NULL, 's'}, @@ -990,19 +1033,23 @@ restore_process = TRUE; last_known_argument++; break; - - case 'v': - verbose = TRUE; - last_known_argument++; - break; + case 'v': + quiet = FALSE ; + verbose = TRUE ; + last_known_argument++ ; + break; case 'q': - quiet = TRUE; - last_known_argument++; + quiet = TRUE ; + verbose = FALSE ; + last_known_argument++ ; + break; + case 'z': + lazy = TRUE ; + last_known_argument++ ; + break; + case 'Z': + lazy = FALSE ; break; - case 'z': - lazy = TRUE; - last_known_argument++; - break; case 'h': print_usage (stdout, 1); last_known_argument++; @@ -1012,7 +1059,7 @@ next_option = -1; break; case '?': - print_usage (stderr, 1); + print_usage (stdout, 1); last_known_argument++; break; case -1: @@ -1130,7 +1177,9 @@ } } - //parameters are all ok! + if (pid_ok) lazy = 1; // --pid forces --lazy + + //parameters are all ok! signal(SIGINT,quit); signal(SIGTERM,quit); @@ -1149,14 +1198,35 @@ wait_for_process: //look for the target process..or wait for it + if (exe != NULL) + pid = getpidof (exe); + if (exe != NULL) - pid=getpidof(exe); + { + for (cp = (char *) exe; (c = (int) *cp) != '\0'; cp++) + { + if (c != '/') continue; + fprintf (stderr, +"Error: -e name should specify a filename without a path\n"); + exit (1); + } + + pid = getpidof (exe); + } else if (path != NULL) - pid=getpidof(path); + { + if (*path != '/') + { + fprintf (stderr, +"Error: -p path should specify an absolute path\n"); + exit (1); + } + + pid = getpidof (path); + } else - waitforpid(pid); + waitforpid (pid); - //process detected...let's play //init compute_cpu_usage internal stuff @@ -1226,7 +1296,8 @@ pcpu_avg=(pcpu_avg*i+pcpu)/(i+1); if (verbose && i%10==0 && i>0) { - printf("%0.2f%%\t%6ld us\t%6ld us\t%0.2f%%\n",pcpu*100,twork.tv_nsec/1000,tsleep.tv_nsec/1000,workingrate*100); +fprintf (stderr, "%0.2f%%\t%6ld us\t%6ld us\t%0.2f%%\n", +pcpu*100,twork.tv_nsec/1000,tsleep.tv_nsec/1000,workingrate*100); if (i%200 == 0) print_caption(); }