View | Details | Raw Unified | Return to bug 159732
Collapse All | Expand All

(-)cpulimit/Makefile (-7 / +4 lines)
Lines 2-21 Link Here
2
# Date created:				30 Mar 2011
2
# Date created:				30 Mar 2011
3
# Whom:					Jesse Smith <jessefrgsmith@yahoo.ca>
3
# Whom:					Jesse Smith <jessefrgsmith@yahoo.ca>
4
#
4
#
5
# $FreeBSD: ports/sysutils/cpulimit/Makefile,v 1.2 2011/04/01 03:46:59 danfe Exp $
5
# $FreeBSD: $
6
#
6
#
7
7
8
PORTNAME=	cpulimit
8
PORTNAME=	cpulimit
9
PORTVERSION=	1.1
9
PORTVERSION=	1.4
10
CATEGORIES=	sysutils
10
CATEGORIES=	sysutils
11
MASTER_SITES=	SF/${PORTNAME}/${PORTNAME}/${PORTNAME}/
11
MASTER_SITES=	SF/limitcpu/limitcpu/
12
12
13
MAINTAINER=	jessefrgsmith@yahoo.ca
13
MAINTAINER=	jessefrgsmith@yahoo.ca
14
COMMENT=	A program to limit the CPU usage of a process
14
COMMENT=	A program to limit the CPU usage of a process
15
15
16
PLIST_FILES=	bin/${PORTNAME}
16
PLIST_FILES=	bin/${PORTNAME} man/man1/${PORTNAME}.1.gz
17
18
do-install:
19
	${INSTALL_PROGRAM} ${WRKSRC}/${PORTNAME} ${PREFIX}/bin
20
17
21
.include <bsd.port.mk>
18
.include <bsd.port.mk>
(-)cpulimit/distinfo (-2 lines)
Lines 1-2 Link Here
1
SHA256 (cpulimit-1.1.tar.gz) = ee734e82692dc496a083c003340b326bd779567f5de99fcae99e451606c85c00
2
SIZE (cpulimit-1.1.tar.gz) = 5130
(-)cpulimit/files/patch-Makefile (+23 lines)
Line 0 Link Here
1
--- ./Makefile.orig	2011-08-12 19:26:33.000000000 -0300
2
+++ ./Makefile	2011-08-12 21:33:31.000000000 -0300
3
@@ -1,16 +1,16 @@
4
-PREFIX?=/usr
5
+PREFIX?=/usr/local
6
 CFLAGS?=-Wall -O2
7
 
8
 all: cpulimit
9
 
10
 cpulimit: cpulimit.c
11
-	gcc -o cpulimit cpulimit.c -lrt $(CFLAGS)
12
+	gcc -o cpulimit cpulimit.c -lrt $(CFLAGS) -lkvm
13
 
14
 install: cpulimit
15
 	mkdir -p ${PREFIX}/bin
16
-	mkdir -p ${PREFIX}/share/man/man1
17
+	mkdir -p ${PREFIX}/man/man1
18
 	cp cpulimit ${PREFIX}/bin
19
-	cp cpulimit.1.gz ${PREFIX}/share/man/man1
20
+	cp cpulimit.1.gz ${PREFIX}/man/man1
21
 
22
 deinstall:
23
 	rm -f ${PREFIX}/bin/cpulimit
(-)cpulimit/files/patch-cpulimit.c (-9 / +9 lines)
Lines 1-8 Link Here
1
--- cpulimit.c.orig	2010-08-20 19:35:15.000000000 -0300
1
--- ./cpulimit.c.orig	2011-08-12 19:35:36.000000000 -0300
2
+++ cpulimit.c	2010-08-21 14:17:52.000000000 -0300
2
+++ ./cpulimit.c	2011-08-12 21:31:58.000000000 -0300
3
@@ -43,6 +43,15 @@
3
@@ -35,6 +35,15 @@
4
 #include <errno.h>
4
 #include <limits.h>    // for compatibility
5
 #include <string.h>
5
 
6
 
6
 
7
+#include <limits.h>
7
+#include <limits.h>
8
+#include <fcntl.h>
8
+#include <fcntl.h>
Lines 16-22 Link Here
16
 //kernel time resolution (inverse of one jiffy interval) in Hertz
16
 //kernel time resolution (inverse of one jiffy interval) in Hertz
17
 //i don't know how to detect it, then define to the default (not very clean!)
17
 //i don't know how to detect it, then define to the default (not very clean!)
18
 #define HZ 100
18
 #define HZ 100
19
@@ -235,6 +244,31 @@
19
@@ -245,6 +254,31 @@
20
 }
20
 }
21
 
21
 
22
 //get jiffies count from /proc filesystem
22
 //get jiffies count from /proc filesystem
Lines 48-56 Link Here
48
 int getjiffies(int pid) {
48
 int getjiffies(int pid) {
49
 	static char stat[20];
49
 	static char stat[20];
50
 	static char buffer[1024];
50
 	static char buffer[1024];
51
@@ -255,6 +289,8 @@
51
@@ -271,6 +305,8 @@
52
 	int ktime=atoi(p+1);
52
         // could not read info
53
 	return utime+ktime;
53
         return -1;
54
 }
54
 }
55
+*/
55
+*/
56
+
56
+
(-)cpulimit/files/patch-makefile (-19 lines)
Lines 1-19 Link Here
1
--- Makefile.old	2005-06-24 07:53:43.000000000 -0300
2
+++ Makefile	2010-08-21 15:10:45.000000000 -0300
3
@@ -1,7 +1,15 @@
4
+PREFIX=/usr/local
5
+
6
 all::	cpulimit
7
 
8
 cpulimit:	cpulimit.c
9
-	gcc -o cpulimit cpulimit.c -lrt -Wall -O2
10
+	gcc -o cpulimit cpulimit.c -lrt -Wall -O2 -lkvm
11
+
12
+install: cpulimit
13
+	cp cpulimit ${PREFIX}/bin
14
+
15
+deinstall:
16
+	rm -f ${PREFIX}/bin/cpulimit
17
 
18
 clean:
19
 	rm -f *~ cpulimit
(-)cpulimit/work/.PLIST.flattened (+2 lines)
Line 0 Link Here
1
/usr/local/bin/cpulimit
2
/usr/local/man/man1/cpulimit.1.gz
(-)cpulimit/work/.PLIST.mktmp (+2 lines)
Line 0 Link Here
1
bin/cpulimit
2
man/man1/cpulimit.1.gz
(-)cpulimit/work/.PLIST.objdump (+41 lines)
Line 0 Link Here
1
2
/usr/local/bin/cpulimit:     file format elf32-i386-freebsd
3
4
DYNAMIC RELOCATION RECORDS
5
OFFSET   TYPE              VALUE 
6
0804b580 R_386_COPY        optarg
7
0804b584 R_386_COPY        __stdoutp
8
0804b588 R_386_COPY        __stderrp
9
0804b500 R_386_JUMP_SLOT   kvm_open
10
0804b504 R_386_JUMP_SLOT   puts
11
0804b508 R_386_JUMP_SLOT   fprintf
12
0804b50c R_386_JUMP_SLOT   atoi
13
0804b510 R_386_JUMP_SLOT   setpriority
14
0804b514 R_386_JUMP_SLOT   kill
15
0804b518 R_386_JUMP_SLOT   strncmp
16
0804b51c R_386_JUMP_SLOT   nanosleep
17
0804b520 R_386_JUMP_SLOT   fork
18
0804b524 R_386_JUMP_SLOT   clock_gettime
19
0804b528 R_386_JUMP_SLOT   _init_tls
20
0804b52c R_386_JUMP_SLOT   abort
21
0804b530 R_386_JUMP_SLOT   opendir
22
0804b534 R_386_JUMP_SLOT   printf
23
0804b538 R_386_JUMP_SLOT   getopt_long
24
0804b53c R_386_JUMP_SLOT   memrchr
25
0804b540 R_386_JUMP_SLOT   signal
26
0804b544 R_386_JUMP_SLOT   fwrite
27
0804b548 R_386_JUMP_SLOT   setsid
28
0804b54c R_386_JUMP_SLOT   exit
29
0804b550 R_386_JUMP_SLOT   readdir
30
0804b554 R_386_JUMP_SLOT   kvm_close
31
0804b558 R_386_JUMP_SLOT   atexit
32
0804b55c R_386_JUMP_SLOT   getpid
33
0804b560 R_386_JUMP_SLOT   strlen
34
0804b564 R_386_JUMP_SLOT   closedir
35
0804b568 R_386_JUMP_SLOT   sleep
36
0804b56c R_386_JUMP_SLOT   sprintf
37
0804b570 R_386_JUMP_SLOT   readlink
38
0804b574 R_386_JUMP_SLOT   perror
39
0804b578 R_386_JUMP_SLOT   kvm_getprocs
40
41
(-)cpulimit/work/cpulimit-1.4/CHANGELOG (+56 lines)
Line 0 Link Here
1
======== Changes in 1.4 ============
2
3
* We can now accept limits of 100% or higher. Useful for multi-core
4
  systems.
5
6
* Perform sanity check when getting jiffies. Should prevent memory
7
  errors if we cannot open proc data.
8
9
* Added copyright to README.
10
11
12
========== Changes in 1.3 ============
13
14
* Updated license information in cpulimit.c and README file
15
16
* The -b flag is now shown under options instead of targets
17
  in the help text.
18
19
* Include man page from Debian with updates.
20
21
22
========= Changes in 1.2 ===========
23
24
* Applied Debian patch for checking to see if and how much we can
25
  adjust our own process priority.
26
27
* Added LICENSE file so there wouldn't be any confusion about
28
  what license CPUlimit uses.
29
30
* Applied Debian's patch for long options to avoid segfault.
31
32
* Applied Debian's Makefile patch.
33
34
* Added Debian patch to avoid opendir leaks.
35
36
* Added -b command line parameter to make CPUlimit 
37
  run in the background, returning control the the 
38
  user's terminal.
39
40
* When cpulimit is launched with one PID to track
41
  once that process no longer exists, CPUlimit
42
  will exit. Same behaviour as though the lazy
43
  flag was set.
44
45
* Ported CPUlimit to FreeBSD
46
47
48
======= cpulimit-1.1 released ============
49
50
* Fixed a segmentation fault if controlled process exited in particular circumstances
51
* Better CPU usage estimate
52
* Fixed a <0 %CPU usage reporting in rare cases
53
* Replaced MAX_PATH_SIZE with PATH_MAX already defined in <limits.h>
54
* Command line arguments now available
55
* Now is possible to specify target process by pid
56
(-)cpulimit/work/cpulimit-1.4/LICENSE (+339 lines)
Line 0 Link Here
1
                    GNU GENERAL PUBLIC LICENSE
2
                       Version 2, June 1991
3
4
 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6
 Everyone is permitted to copy and distribute verbatim copies
7
 of this license document, but changing it is not allowed.
8
9
                            Preamble
10
11
  The licenses for most software are designed to take away your
12
freedom to share and change it.  By contrast, the GNU General Public
13
License is intended to guarantee your freedom to share and change free
14
software--to make sure the software is free for all its users.  This
15
General Public License applies to most of the Free Software
16
Foundation's software and to any other program whose authors commit to
17
using it.  (Some other Free Software Foundation software is covered by
18
the GNU Lesser General Public License instead.)  You can apply it to
19
your programs, too.
20
21
  When we speak of free software, we are referring to freedom, not
22
price.  Our General Public Licenses are designed to make sure that you
23
have the freedom to distribute copies of free software (and charge for
24
this service if you wish), that you receive source code or can get it
25
if you want it, that you can change the software or use pieces of it
26
in new free programs; and that you know you can do these things.
27
28
  To protect your rights, we need to make restrictions that forbid
29
anyone to deny you these rights or to ask you to surrender the rights.
30
These restrictions translate to certain responsibilities for you if you
31
distribute copies of the software, or if you modify it.
32
33
  For example, if you distribute copies of such a program, whether
34
gratis or for a fee, you must give the recipients all the rights that
35
you have.  You must make sure that they, too, receive or can get the
36
source code.  And you must show them these terms so they know their
37
rights.
38
39
  We protect your rights with two steps: (1) copyright the software, and
40
(2) offer you this license which gives you legal permission to copy,
41
distribute and/or modify the software.
42
43
  Also, for each author's protection and ours, we want to make certain
44
that everyone understands that there is no warranty for this free
45
software.  If the software is modified by someone else and passed on, we
46
want its recipients to know that what they have is not the original, so
47
that any problems introduced by others will not reflect on the original
48
authors' reputations.
49
50
  Finally, any free program is threatened constantly by software
51
patents.  We wish to avoid the danger that redistributors of a free
52
program will individually obtain patent licenses, in effect making the
53
program proprietary.  To prevent this, we have made it clear that any
54
patent must be licensed for everyone's free use or not licensed at all.
55
56
  The precise terms and conditions for copying, distribution and
57
modification follow.
58
59
                    GNU GENERAL PUBLIC LICENSE
60
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62
  0. This License applies to any program or other work which contains
63
a notice placed by the copyright holder saying it may be distributed
64
under the terms of this General Public License.  The "Program", below,
65
refers to any such program or work, and a "work based on the Program"
66
means either the Program or any derivative work under copyright law:
67
that is to say, a work containing the Program or a portion of it,
68
either verbatim or with modifications and/or translated into another
69
language.  (Hereinafter, translation is included without limitation in
70
the term "modification".)  Each licensee is addressed as "you".
71
72
Activities other than copying, distribution and modification are not
73
covered by this License; they are outside its scope.  The act of
74
running the Program is not restricted, and the output from the Program
75
is covered only if its contents constitute a work based on the
76
Program (independent of having been made by running the Program).
77
Whether that is true depends on what the Program does.
78
79
  1. You may copy and distribute verbatim copies of the Program's
80
source code as you receive it, in any medium, provided that you
81
conspicuously and appropriately publish on each copy an appropriate
82
copyright notice and disclaimer of warranty; keep intact all the
83
notices that refer to this License and to the absence of any warranty;
84
and give any other recipients of the Program a copy of this License
85
along with the Program.
86
87
You may charge a fee for the physical act of transferring a copy, and
88
you may at your option offer warranty protection in exchange for a fee.
89
90
  2. You may modify your copy or copies of the Program or any portion
91
of it, thus forming a work based on the Program, and copy and
92
distribute such modifications or work under the terms of Section 1
93
above, provided that you also meet all of these conditions:
94
95
    a) You must cause the modified files to carry prominent notices
96
    stating that you changed the files and the date of any change.
97
98
    b) You must cause any work that you distribute or publish, that in
99
    whole or in part contains or is derived from the Program or any
100
    part thereof, to be licensed as a whole at no charge to all third
101
    parties under the terms of this License.
102
103
    c) If the modified program normally reads commands interactively
104
    when run, you must cause it, when started running for such
105
    interactive use in the most ordinary way, to print or display an
106
    announcement including an appropriate copyright notice and a
107
    notice that there is no warranty (or else, saying that you provide
108
    a warranty) and that users may redistribute the program under
109
    these conditions, and telling the user how to view a copy of this
110
    License.  (Exception: if the Program itself is interactive but
111
    does not normally print such an announcement, your work based on
112
    the Program is not required to print an announcement.)
113
114
These requirements apply to the modified work as a whole.  If
115
identifiable sections of that work are not derived from the Program,
116
and can be reasonably considered independent and separate works in
117
themselves, then this License, and its terms, do not apply to those
118
sections when you distribute them as separate works.  But when you
119
distribute the same sections as part of a whole which is a work based
120
on the Program, the distribution of the whole must be on the terms of
121
this License, whose permissions for other licensees extend to the
122
entire whole, and thus to each and every part regardless of who wrote it.
123
124
Thus, it is not the intent of this section to claim rights or contest
125
your rights to work written entirely by you; rather, the intent is to
126
exercise the right to control the distribution of derivative or
127
collective works based on the Program.
128
129
In addition, mere aggregation of another work not based on the Program
130
with the Program (or with a work based on the Program) on a volume of
131
a storage or distribution medium does not bring the other work under
132
the scope of this License.
133
134
  3. You may copy and distribute the Program (or a work based on it,
135
under Section 2) in object code or executable form under the terms of
136
Sections 1 and 2 above provided that you also do one of the following:
137
138
    a) Accompany it with the complete corresponding machine-readable
139
    source code, which must be distributed under the terms of Sections
140
    1 and 2 above on a medium customarily used for software interchange; or,
141
142
    b) Accompany it with a written offer, valid for at least three
143
    years, to give any third party, for a charge no more than your
144
    cost of physically performing source distribution, a complete
145
    machine-readable copy of the corresponding source code, to be
146
    distributed under the terms of Sections 1 and 2 above on a medium
147
    customarily used for software interchange; or,
148
149
    c) Accompany it with the information you received as to the offer
150
    to distribute corresponding source code.  (This alternative is
151
    allowed only for noncommercial distribution and only if you
152
    received the program in object code or executable form with such
153
    an offer, in accord with Subsection b above.)
154
155
The source code for a work means the preferred form of the work for
156
making modifications to it.  For an executable work, complete source
157
code means all the source code for all modules it contains, plus any
158
associated interface definition files, plus the scripts used to
159
control compilation and installation of the executable.  However, as a
160
special exception, the source code distributed need not include
161
anything that is normally distributed (in either source or binary
162
form) with the major components (compiler, kernel, and so on) of the
163
operating system on which the executable runs, unless that component
164
itself accompanies the executable.
165
166
If distribution of executable or object code is made by offering
167
access to copy from a designated place, then offering equivalent
168
access to copy the source code from the same place counts as
169
distribution of the source code, even though third parties are not
170
compelled to copy the source along with the object code.
171
172
  4. You may not copy, modify, sublicense, or distribute the Program
173
except as expressly provided under this License.  Any attempt
174
otherwise to copy, modify, sublicense or distribute the Program is
175
void, and will automatically terminate your rights under this License.
176
However, parties who have received copies, or rights, from you under
177
this License will not have their licenses terminated so long as such
178
parties remain in full compliance.
179
180
  5. You are not required to accept this License, since you have not
181
signed it.  However, nothing else grants you permission to modify or
182
distribute the Program or its derivative works.  These actions are
183
prohibited by law if you do not accept this License.  Therefore, by
184
modifying or distributing the Program (or any work based on the
185
Program), you indicate your acceptance of this License to do so, and
186
all its terms and conditions for copying, distributing or modifying
187
the Program or works based on it.
188
189
  6. Each time you redistribute the Program (or any work based on the
190
Program), the recipient automatically receives a license from the
191
original licensor to copy, distribute or modify the Program subject to
192
these terms and conditions.  You may not impose any further
193
restrictions on the recipients' exercise of the rights granted herein.
194
You are not responsible for enforcing compliance by third parties to
195
this License.
196
197
  7. If, as a consequence of a court judgment or allegation of patent
198
infringement or for any other reason (not limited to patent issues),
199
conditions are imposed on you (whether by court order, agreement or
200
otherwise) that contradict the conditions of this License, they do not
201
excuse you from the conditions of this License.  If you cannot
202
distribute so as to satisfy simultaneously your obligations under this
203
License and any other pertinent obligations, then as a consequence you
204
may not distribute the Program at all.  For example, if a patent
205
license would not permit royalty-free redistribution of the Program by
206
all those who receive copies directly or indirectly through you, then
207
the only way you could satisfy both it and this License would be to
208
refrain entirely from distribution of the Program.
209
210
If any portion of this section is held invalid or unenforceable under
211
any particular circumstance, the balance of the section is intended to
212
apply and the section as a whole is intended to apply in other
213
circumstances.
214
215
It is not the purpose of this section to induce you to infringe any
216
patents or other property right claims or to contest validity of any
217
such claims; this section has the sole purpose of protecting the
218
integrity of the free software distribution system, which is
219
implemented by public license practices.  Many people have made
220
generous contributions to the wide range of software distributed
221
through that system in reliance on consistent application of that
222
system; it is up to the author/donor to decide if he or she is willing
223
to distribute software through any other system and a licensee cannot
224
impose that choice.
225
226
This section is intended to make thoroughly clear what is believed to
227
be a consequence of the rest of this License.
228
229
  8. If the distribution and/or use of the Program is restricted in
230
certain countries either by patents or by copyrighted interfaces, the
231
original copyright holder who places the Program under this License
232
may add an explicit geographical distribution limitation excluding
233
those countries, so that distribution is permitted only in or among
234
countries not thus excluded.  In such case, this License incorporates
235
the limitation as if written in the body of this License.
236
237
  9. The Free Software Foundation may publish revised and/or new versions
238
of the General Public License from time to time.  Such new versions will
239
be similar in spirit to the present version, but may differ in detail to
240
address new problems or concerns.
241
242
Each version is given a distinguishing version number.  If the Program
243
specifies a version number of this License which applies to it and "any
244
later version", you have the option of following the terms and conditions
245
either of that version or of any later version published by the Free
246
Software Foundation.  If the Program does not specify a version number of
247
this License, you may choose any version ever published by the Free Software
248
Foundation.
249
250
  10. If you wish to incorporate parts of the Program into other free
251
programs whose distribution conditions are different, write to the author
252
to ask for permission.  For software which is copyrighted by the Free
253
Software Foundation, write to the Free Software Foundation; we sometimes
254
make exceptions for this.  Our decision will be guided by the two goals
255
of preserving the free status of all derivatives of our free software and
256
of promoting the sharing and reuse of software generally.
257
258
                            NO WARRANTY
259
260
  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
262
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
266
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
267
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
REPAIR OR CORRECTION.
269
270
  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
POSSIBILITY OF SUCH DAMAGES.
279
280
                     END OF TERMS AND CONDITIONS
281
282
            How to Apply These Terms to Your New Programs
283
284
  If you develop a new program, and you want it to be of the greatest
285
possible use to the public, the best way to achieve this is to make it
286
free software which everyone can redistribute and change under these terms.
287
288
  To do so, attach the following notices to the program.  It is safest
289
to attach them to the start of each source file to most effectively
290
convey the exclusion of warranty; and each file should have at least
291
the "copyright" line and a pointer to where the full notice is found.
292
293
    <one line to give the program's name and a brief idea of what it does.>
294
    Copyright (C) <year>  <name of author>
295
296
    This program is free software; you can redistribute it and/or modify
297
    it under the terms of the GNU General Public License as published by
298
    the Free Software Foundation; either version 2 of the License, or
299
    (at your option) any later version.
300
301
    This program is distributed in the hope that it will be useful,
302
    but WITHOUT ANY WARRANTY; without even the implied warranty of
303
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
304
    GNU General Public License for more details.
305
306
    You should have received a copy of the GNU General Public License along
307
    with this program; if not, write to the Free Software Foundation, Inc.,
308
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
310
Also add information on how to contact you by electronic and paper mail.
311
312
If the program is interactive, make it output a short notice like this
313
when it starts in an interactive mode:
314
315
    Gnomovision version 69, Copyright (C) year name of author
316
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317
    This is free software, and you are welcome to redistribute it
318
    under certain conditions; type `show c' for details.
319
320
The hypothetical commands `show w' and `show c' should show the appropriate
321
parts of the General Public License.  Of course, the commands you use may
322
be called something other than `show w' and `show c'; they could even be
323
mouse-clicks or menu items--whatever suits your program.
324
325
You should also get your employer (if you work as a programmer) or your
326
school, if any, to sign a "copyright disclaimer" for the program, if
327
necessary.  Here is a sample; alter the names:
328
329
  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330
  `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
332
  <signature of Ty Coon>, 1 April 1989
333
  Ty Coon, President of Vice
334
335
This General Public License does not permit incorporating your program into
336
proprietary programs.  If your program is a subroutine library, you may
337
consider it more useful to permit linking proprietary applications with the
338
library.  If this is what you want to do, use the GNU Lesser General
339
Public License instead of this License.
(-)cpulimit/work/cpulimit-1.4/Makefile (+20 lines)
Line 0 Link Here
1
PREFIX?=/usr/local
2
CFLAGS?=-Wall -O2
3
4
all: cpulimit
5
6
cpulimit: cpulimit.c
7
	gcc -o cpulimit cpulimit.c -lrt $(CFLAGS) -lkvm
8
9
install: cpulimit
10
	mkdir -p ${PREFIX}/bin
11
	mkdir -p ${PREFIX}/man/man1
12
	cp cpulimit ${PREFIX}/bin
13
	cp cpulimit.1.gz ${PREFIX}/man/man1
14
15
deinstall:
16
	rm -f ${PREFIX}/bin/cpulimit
17
	rm -f ${PREFIX}/share/man/man1/cpulimit.1.gz
18
19
clean:
20
	rm -f *~ cpulimit
(-)cpulimit/work/cpulimit-1.4/Makefile.orig (+20 lines)
Line 0 Link Here
1
PREFIX?=/usr
2
CFLAGS?=-Wall -O2
3
4
all: cpulimit
5
6
cpulimit: cpulimit.c
7
	gcc -o cpulimit cpulimit.c -lrt $(CFLAGS)
8
9
install: cpulimit
10
	mkdir -p ${PREFIX}/bin
11
	mkdir -p ${PREFIX}/share/man/man1
12
	cp cpulimit ${PREFIX}/bin
13
	cp cpulimit.1.gz ${PREFIX}/share/man/man1
14
15
deinstall:
16
	rm -f ${PREFIX}/bin/cpulimit
17
	rm -f ${PREFIX}/share/man/man1/cpulimit.1.gz
18
19
clean:
20
	rm -f *~ cpulimit
(-)cpulimit/work/cpulimit-1.4/README (+105 lines)
Line 0 Link Here
1
README for LimitCPU
2
==========================
3
4
LimitCPU is a program to throttle the CPU cycles used by other applications.
5
LimitCPU will monitor a process and make sure its CPU usage stays at or
6
below a given percentage. This can be used to make sure your system
7
has plenty of CPU cycles available for other tasks. It can also be used
8
to keep laptops cool in the face of CPU-hungry processes and for limiting
9
virtual machines.
10
11
LimitCPU is the direct child of CPUlimit, a creation of Angelo Marletta,
12
which can be found at http://cpulimit.sourceforge.net.
13
14
15
16
17
Copying, License and Distribution
18
===================================
19
20
LimitCPU is licensed under the GNU General Public License (version 2).
21
A copy of the license should be included with this program in a
22
file named LICENSE.
23
24
Copyright 2005, Angelo Marletta <marlonx80@hotmail.com>
25
Copyright 2011, Jesse Smith <jessefrgsmith@yahoo.ca>
26
27
28
29
30
31
Where to get LimitCPU
32
==========================
33
34
The LimitCPU program can be aquired from http://limitcpu.sourceforge.net
35
36
37
38
39
How to compile and install
40
===========================
41
42
Once you have downloaded a copy of LimitCPU building should be fairly
43
straight forward. First we unpack the source code
44
45
tar zxf cpulimit-1.4.tar.gz
46
47
Then we run the makefile.
48
49
cd cpulimit-1.4
50
make
51
52
This should produce the executable file "cpulimit". If you would like
53
to install the program to make it available system-wide, run
54
55
make install
56
57
58
Later should you wish to remove the program from your system, run
59
the following command from the limitcpu directory
60
61
make deinstall
62
63
64
65
Common usage
66
==========================
67
68
The LimitCPU program is generally used to throttle the CPU usage of
69
one process. This can be done with the following command where
70
12345 is the process ID number of a running program and 25 is the
71
maximum percentage of the CPU we are willing to give that program
72
73
cpulimit -p 12345 -l 25
74
75
The above example will cause LimitCPU to keep an eye on the process
76
with ID number 12345 until the program exits. Should we wish to
77
run LimitCPU in the background we can use
78
79
cpulimit -p 12345 -l 25 -b
80
81
We can also limit running processes based on their name instead of
82
their process ID, as in this example:
83
84
cpulimit --exe /usr/bin/bigexe --limit 50
85
86
The above example will keep an eye on "bigexe" and, if the application
87
quits and another program called "bigexe" is run, LimitCPU will
88
monitor the new process too. Should we wish to only track the first
89
program and then exit, we can use 
90
91
cpulimit --exec /usr/bin/bigexe --limit 50 -z
92
93
The "-z" flag tells LimitCPU to stop running once its target is
94
no longer running itself.
95
96
97
98
99
Bugs and Feedback
100
=============================
101
102
Should you have comments, questions, or bugs to report, please send
103
an e-mail to jessefrgsmith@yahoo.ca with the word "LimitCPU" in the
104
subject line.
105
(-)cpulimit/work/cpulimit-1.4/cpulimit.c (+655 lines)
Line 0 Link Here
1
/**
2
 * This program is licensed under the GNU General Public License,
3
 * version 2. A copy of the license can be found in the accompanying
4
 * LICENSE file.
5
 *
6
 **********************************************************************
7
 *
8
 * Simple program to limit the cpu usage of a process
9
 * If you modify this code, send me a copy please
10
 *
11
 * Author:  Angelo Marletta
12
 * Date:    26/06/2005
13
 * Version: 1.1
14
 *
15
 * Modifications and updates by: Jesse Smith
16
 * Date: May 4, 2011
17
 * Version 1.2
18
 *
19
 */
20
21
22
#include <getopt.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <time.h>
26
#include <sys/time.h>
27
#include <unistd.h>
28
#include <sys/types.h>
29
#include <signal.h>
30
#include <sys/resource.h>
31
#include <string.h>
32
#include <dirent.h>
33
#include <errno.h>
34
#include <string.h>
35
#include <limits.h>    // for compatibility
36
37
38
#include <limits.h>
39
#include <fcntl.h>
40
#include <kvm.h>
41
#include <paths.h>
42
#include <sys/param.h>
43
#include <sys/sysctl.h>
44
#include <sys/user.h>
45
46
47
//kernel time resolution (inverse of one jiffy interval) in Hertz
48
//i don't know how to detect it, then define to the default (not very clean!)
49
#define HZ 100
50
51
//some useful macro
52
#define min(a,b) (a<b?a:b)
53
#define max(a,b) (a>b?a:b)
54
55
//pid of the controlled process
56
int pid=0;
57
//executable file name
58
char *program_name;
59
//verbose mode
60
int verbose=0;
61
//lazy mode
62
int lazy=0;
63
// is higher priority nice possible?
64
int nice_lim;
65
66
//reverse byte search
67
void *memrchr(const void *s, int c, size_t n);
68
69
//return ta-tb in microseconds (no overflow checks!)
70
inline long timediff(const struct timespec *ta,const struct timespec *tb) {
71
    unsigned long us = (ta->tv_sec-tb->tv_sec)*1000000 + (ta->tv_nsec/1000 - tb->tv_nsec/1000);
72
    return us;
73
}
74
75
int waitforpid(int pid) {
76
	//switch to low priority
77
	// if (setpriority(PRIO_PROCESS,getpid(),19)!=0) {
78
        if ( (nice_lim < INT_MAX) && 
79
             (setpriority(PRIO_PROCESS, getpid(), 19) != 0) ) {
80
		printf("Warning: cannot renice\n");
81
	}
82
83
	int i=0;
84
85
	while(1) {
86
87
		DIR *dip;
88
		struct dirent *dit;
89
90
		//open a directory stream to /proc directory
91
		if ((dip = opendir("/proc")) == NULL) {
92
			perror("opendir");
93
			return -1;
94
		}
95
96
		//read in from /proc and seek for process dirs
97
		while ((dit = readdir(dip)) != NULL) {
98
			//get pid
99
			if (pid==atoi(dit->d_name)) {
100
				//pid detected
101
				if (kill(pid,SIGSTOP)==0 &&  kill(pid,SIGCONT)==0) {
102
					//process is ok!
103
                                        if (closedir(dip) == -1) {
104
                                           perror("closedir");
105
                                           return -1;
106
                                        }
107
					goto done;
108
				}
109
				else {
110
					fprintf(stderr,"Error: Process %d detected, but you don't have permission to control it\n",pid);
111
				}
112
			}
113
		}
114
115
		//close the dir stream and check for errors
116
		if (closedir(dip) == -1) {
117
			perror("closedir");
118
			return -1;
119
		}
120
121
		//no suitable target found
122
		if (i++==0) {
123
			if (lazy) {
124
				fprintf(stderr,"No process found\n");
125
				exit(2);
126
			}
127
			else {
128
				printf("Warning: no target process found. Waiting for it...\n");
129
			}
130
		}
131
132
		//sleep for a while
133
		sleep(2);
134
	}
135
136
done:
137
	printf("Process %d detected\n",pid);
138
	//now set high priority, if possible
139
	// if (setpriority(PRIO_PROCESS,getpid(),-20)!=0) {
140
        if ( (nice_lim < INT_MAX) &&
141
             (setpriority(PRIO_PROCESS, getpid(), nice_lim) != 0) ) {
142
		printf("Warning: cannot renice.\nTo work better you should run this program as root.\n");
143
	}
144
	return 0;
145
146
}
147
148
//this function periodically scans process list and looks for executable path names
149
//it should be executed in a low priority context, since precise timing does not matter
150
//if a process is found then its pid is returned
151
//process: the name of the wanted process, can be an absolute path name to the executable file
152
//         or simply its name
153
//return: pid of the found process
154
int getpidof(const char *process) {
155
156
	//set low priority
157
	// if (setpriority(PRIO_PROCESS,getpid(),19)!=0) {
158
        if ( (nice_lim < INT_MAX) &&
159
             (setpriority(PRIO_PROCESS, getpid(), 19) != 0) ) {
160
		printf("Warning: cannot renice\n");
161
	}
162
163
	char exelink[20];
164
	char exepath[PATH_MAX+1];
165
	int pid=0;
166
	int i=0;
167
168
	while(1) {
169
170
		DIR *dip;
171
		struct dirent *dit;
172
173
		//open a directory stream to /proc directory
174
		if ((dip = opendir("/proc")) == NULL) {
175
			perror("opendir");
176
			return -1;
177
		}
178
179
		//read in from /proc and seek for process dirs
180
		while ((dit = readdir(dip)) != NULL) {
181
			//get pid
182
			pid=atoi(dit->d_name);
183
			if (pid>0) {
184
				sprintf(exelink,"/proc/%d/exe",pid);
185
				int size=readlink(exelink,exepath,sizeof(exepath));
186
				if (size>0) {
187
					int found=0;
188
					if (process[0]=='/' && strncmp(exepath,process,size)==0 && size==strlen(process)) {
189
						//process starts with / then it's an absolute path
190
						found=1;
191
					}
192
					else {
193
						//process is the name of the executable file
194
						if (strncmp(exepath+size-strlen(process),process,strlen(process))==0) {
195
							found=1;
196
						}
197
					}
198
					if (found==1) {
199
						if (kill(pid,SIGSTOP)==0 &&  kill(pid,SIGCONT)==0) {
200
							//process is ok!
201
                                                        if (closedir(dip) == -1) {
202
                                                          perror("closedir");
203
                                                          return -1;
204
                                                        }
205
							goto done;
206
						}
207
						else {
208
							fprintf(stderr,"Error: Process %d detected, but you don't have permission to control it\n",pid);
209
						}
210
					}
211
				}
212
			}
213
		}
214
215
		//close the dir stream and check for errors
216
		if (closedir(dip) == -1) {
217
			perror("closedir");
218
			return -1;
219
		}
220
221
		//no suitable target found
222
		if (i++==0) {
223
			if (lazy) {
224
				fprintf(stderr,"No process found\n");
225
				exit(2);
226
			}
227
			else {
228
				printf("Warning: no target process found. Waiting for it...\n");
229
			}
230
		}
231
232
		//sleep for a while
233
		sleep(2);
234
	}
235
236
done:
237
	printf("Process %d detected\n",pid);
238
	//now set high priority, if possible
239
	// if (setpriority(PRIO_PROCESS,getpid(),-20)!=0) {
240
        if ( (nice_lim < INT_MAX) &&
241
             (setpriority(PRIO_PROCESS, getpid(), nice_lim) != 0) ) {
242
		printf("Warning: cannot renice.\nTo work better you should run this program as root.\n");
243
	}
244
	return pid;
245
246
}
247
248
//SIGINT and SIGTERM signal handler
249
void quit(int sig) {
250
	//let the process continue if it's stopped
251
	kill(pid,SIGCONT);
252
	printf("Exiting...\n");
253
	exit(0);
254
}
255
256
//get jiffies count from /proc filesystem
257
int getjiffies(int pid)
258
{
259
   kvm_t *my_kernel = NULL;
260
   struct kinfo_proc *process_data = NULL;
261
   int processes;
262
   int my_jiffies = -1;
263
264
   my_kernel = kvm_open(0, 0, 0, O_RDONLY, "kvm_open");
265
   if (! my_kernel)
266
   {
267
      printf("Error opening kernel vm. You should be running as root.\n");
268
      return -1;
269
   }
270
271
   process_data = kvm_getprocs(my_kernel, KERN_PROC_PID, pid, &processes);
272
   if ( (process_data) && (processes >= 1) )
273
       my_jiffies = process_data->ki_runtime;
274
   
275
   kvm_close(my_kernel);
276
   if (my_jiffies >= 0)
277
     my_jiffies /= 1000;
278
   return my_jiffies;
279
}
280
281
/*
282
int getjiffies(int pid) {
283
	static char stat[20];
284
	static char buffer[1024];
285
        char *p;
286
	sprintf(stat,"/proc/%d/stat",pid);
287
	FILE *f=fopen(stat,"r");
288
	if (f==NULL) return -1;
289
	p = fgets(buffer,sizeof(buffer),f);
290
	fclose(f);
291
	// char *p=buffer;
292
        if (p)
293
        {
294
	  p=memchr(p+1,')',sizeof(buffer)-(p-buffer));
295
	  int sp=12;
296
	  while (sp--)
297
		p=memchr(p+1,' ',sizeof(buffer)-(p-buffer));
298
	  //user mode jiffies
299
	  int utime=atoi(p+1);
300
	  p=memchr(p+1,' ',sizeof(buffer)-(p-buffer));
301
	  //kernel mode jiffies
302
	  int ktime=atoi(p+1);
303
	  return utime+ktime;
304
        }
305
        // could not read info
306
        return -1;
307
}
308
*/
309
310
311
//process instant photo
312
struct process_screenshot {
313
	struct timespec when;	//timestamp
314
	int jiffies;	//jiffies count of the process
315
	int cputime;	//microseconds of work from previous screenshot to current
316
};
317
318
//extracted process statistics
319
struct cpu_usage {
320
	float pcpu;
321
	float workingrate;
322
};
323
324
//this function is an autonomous dynamic system
325
//it works with static variables (state variables of the system), that keep memory of recent past
326
//its aim is to estimate the cpu usage of the process
327
//to work properly it should be called in a fixed periodic way
328
//perhaps i will put it in a separate thread...
329
int compute_cpu_usage(int pid,int last_working_quantum,struct cpu_usage *pusage) {
330
	#define MEM_ORDER 10
331
	//circular buffer containing last MEM_ORDER process screenshots
332
	static struct process_screenshot ps[MEM_ORDER];
333
	//the last screenshot recorded in the buffer
334
	static int front=-1;
335
	//the oldest screenshot recorded in the buffer
336
	static int tail=0;
337
338
	if (pusage==NULL) {
339
		//reinit static variables
340
		front=-1;
341
		tail=0;
342
		return 0;
343
	}
344
345
	//let's advance front index and save the screenshot
346
	front=(front+1)%MEM_ORDER;
347
	int j=getjiffies(pid);
348
	if (j>=0) ps[front].jiffies=j;
349
	else return -1;	//error: pid does not exist
350
	clock_gettime(CLOCK_REALTIME,&(ps[front].when));
351
	ps[front].cputime=last_working_quantum;
352
353
	//buffer actual size is: (front-tail+MEM_ORDER)%MEM_ORDER+1
354
	int size=(front-tail+MEM_ORDER)%MEM_ORDER+1;
355
356
	if (size==1) {
357
		//not enough samples taken (it's the first one!), return -1
358
		pusage->pcpu=-1;
359
		pusage->workingrate=1;
360
		return 0;
361
	}
362
	else {
363
		//now we can calculate cpu usage, interval dt and dtwork are expressed in microseconds
364
		long dt=timediff(&(ps[front].when),&(ps[tail].when));
365
		long dtwork=0;
366
		int i=(tail+1)%MEM_ORDER;
367
		int max=(front+1)%MEM_ORDER;
368
		do {
369
			dtwork+=ps[i].cputime;
370
			i=(i+1)%MEM_ORDER;
371
		} while (i!=max);
372
		int used=ps[front].jiffies-ps[tail].jiffies;
373
		float usage=(used*1000000.0/HZ)/dtwork;
374
		pusage->workingrate=1.0*dtwork/dt;
375
		pusage->pcpu=usage*pusage->workingrate;
376
		if (size==MEM_ORDER)
377
			tail=(tail+1)%MEM_ORDER;
378
		return 0;
379
	}
380
	#undef MEM_ORDER
381
}
382
383
void print_caption() {
384
	printf("\n%%CPU\twork quantum\tsleep quantum\tactive rate\n");
385
}
386
387
void print_usage(FILE *stream,int exit_code) {
388
	fprintf(stream, "Usage: %s TARGET [OPTIONS...]\n",program_name);
389
	fprintf(stream, "   TARGET must be exactly one of these:\n");
390
	fprintf(stream, "      -p, --pid=N        pid of the process\n");
391
	fprintf(stream, "      -e, --exe=FILE     name of the executable program file\n");
392
	fprintf(stream, "      -P, --path=PATH    absolute path name of the executable program file\n");
393
	fprintf(stream, "   OPTIONS\n");
394
        fprintf(stream, "      -b  --background   run in background\n");
395
	fprintf(stream, "      -l, --limit=N      percentage of cpu allowed from 0 to 100 (mandatory)\n");
396
	fprintf(stream, "      -v, --verbose      show control statistics\n");
397
	fprintf(stream, "      -z, --lazy         exit if there is no suitable target process, or if it dies\n");
398
	fprintf(stream, "      -h, --help         display this help and exit\n");
399
	exit(exit_code);
400
}
401
402
int main(int argc, char **argv) {
403
404
	//get program name
405
	char *p=(char*)memrchr(argv[0],(unsigned int)'/',strlen(argv[0]));
406
	program_name = p==NULL?argv[0]:(p+1);
407
        int run_in_background = 0;
408
	//parse arguments
409
	int next_option;
410
	/* A string listing valid short options letters. */
411
	const char* short_options="p:e:P:l:bvzh";
412
	/* An array describing valid long options. */
413
	const struct option long_options[] = {
414
		{ "pid", required_argument, NULL, 'p' },
415
		{ "exe", required_argument, NULL, 'e' },
416
		{ "path", required_argument, NULL, 'P' },
417
		{ "limit", required_argument, NULL, 'l' },
418
                { "background", no_argument, NULL, 'b' },
419
		{ "verbose", no_argument, NULL, 'v' },
420
		{ "lazy", no_argument, NULL, 'z' },
421
		{ "help", no_argument, NULL, 'h' },
422
		{ NULL, 0, NULL, 0 }
423
	};
424
	//argument variables
425
	const char *exe=NULL;
426
	const char *path=NULL;
427
	int perclimit=0;
428
	int pid_ok=0;
429
	int process_ok=0;
430
	int limit_ok=0;
431
        struct rlimit maxlimit;
432
433
	do {
434
		next_option = getopt_long (argc, argv, short_options,long_options, NULL);
435
		switch(next_option) {
436
                        case 'b':
437
                                run_in_background = 1;
438
                                break;
439
			case 'p':
440
				pid=atoi(optarg);
441
				pid_ok=1;
442
                                lazy = 1;
443
				break;
444
			case 'e':
445
				exe=optarg;
446
				process_ok=1;
447
				break;
448
			case 'P':
449
				path=optarg;
450
				process_ok=1;
451
				break;
452
			case 'l':
453
				perclimit=atoi(optarg);
454
				limit_ok=1;
455
				break;
456
			case 'v':
457
				verbose=1;
458
				break;
459
			case 'z':
460
				lazy=1;
461
				break;
462
			case 'h':
463
				print_usage (stdout, 1);
464
				break;
465
			case '?':
466
				print_usage (stderr, 1);
467
				break;
468
			case -1:
469
				break;
470
			default:
471
				abort();
472
		}
473
	} while(next_option != -1);
474
475
	if (!process_ok && !pid_ok) {
476
		fprintf(stderr,"Error: You must specify a target process\n");
477
		print_usage (stderr, 1);
478
		exit(1);
479
	}
480
	if ((exe!=NULL && path!=NULL) || (pid_ok && (exe!=NULL || path!=NULL))) {
481
		fprintf(stderr,"Error: You must specify exactly one target process\n");
482
		print_usage (stderr, 1);
483
		exit(1);
484
	}
485
	if (!limit_ok) {
486
		fprintf(stderr,"Error: You must specify a cpu limit\n");
487
		print_usage (stderr, 1);
488
		exit(1);
489
	}
490
	float limit=perclimit/100.0;
491
	if (limit <= 0.00) // || limit >1) {
492
        {
493
		fprintf(stderr,"Error: limit must be greater than 0\n");
494
		print_usage (stderr, 1);
495
		exit(1);
496
	}
497
498
        // check to see if we should fork
499
        if (run_in_background)
500
        {
501
             pid_t process_id;
502
             process_id = fork();
503
             if (! process_id)
504
                exit(0);
505
             else
506
             {
507
                setsid();
508
                process_id = fork();
509
                if (process_id)
510
                  exit(0);
511
             }
512
        }
513
514
	//parameters are all ok!
515
	signal(SIGINT,quit);
516
	signal(SIGTERM,quit);
517
518
	if (setpriority(PRIO_PROCESS,getpid(),-20)!=0) {
519
	//if that failed, check if we have a limit 
520
        // by how much we can raise the priority
521
#ifdef RLIMIT_NICE 
522
//check if non-root can even make changes 
523
// (ifdef because it's only available in linux >= 2.6.13)
524
		nice_lim=getpriority(PRIO_PROCESS,getpid());
525
		getrlimit(RLIMIT_NICE, &maxlimit);
526
527
//if we can do better then current
528
		if( (20 - (signed)maxlimit.rlim_cur) < nice_lim &&  
529
		    setpriority(PRIO_PROCESS,getpid(),
530
                    20 - (signed)maxlimit.rlim_cur)==0 //and it actually works
531
		  ) {
532
533
			//if we can do better, but not by much, warn about it
534
			if( (nice_lim - (20 - (signed)maxlimit.rlim_cur)) < 9) 
535
                        {
536
			printf("Warning, can only increase priority by %d.\n",                                nice_lim - (20 - (signed)maxlimit.rlim_cur));
537
			}
538
                        //our new limit
539
			nice_lim = 20 - (signed)maxlimit.rlim_cur; 
540
541
		} else 
542
// otherwise don't try to change priority. 
543
// The below will also run if it's not possible 
544
// for non-root to change priority
545
#endif
546
		{
547
			printf("Warning: cannot renice.\nTo work better you should run this program as root, or adjust RLIMIT_NICE.\nFor example in /etc/security/limits.conf add a line with: * - nice -10\n\n");
548
			nice_lim=INT_MAX;
549
		}
550
	} else {
551
		nice_lim=-20;
552
	}
553
	//don't bother putting setpriority back down, 
554
        // since getpidof and waitforpid twiddle it anyway
555
556
557
558
	//time quantum in microseconds. it's splitted in a working period and a sleeping one
559
	int period=100000;
560
	struct timespec twork,tsleep;   //working and sleeping intervals
561
	memset(&twork,0,sizeof(struct timespec));
562
	memset(&tsleep,0,sizeof(struct timespec));
563
564
wait_for_process:
565
566
	//look for the target process..or wait for it
567
	if (exe!=NULL)
568
		pid=getpidof(exe);
569
	else if (path!=NULL)
570
		pid=getpidof(path);
571
	else {
572
		waitforpid(pid);
573
	}
574
	//process detected...let's play
575
576
	//init compute_cpu_usage internal stuff
577
	compute_cpu_usage(0,0,NULL);
578
	//main loop counter
579
	int i=0;
580
581
	struct timespec startwork,endwork;
582
	long workingtime=0;		//last working time in microseconds
583
584
	if (verbose) print_caption();
585
586
	float pcpu_avg=0;
587
588
	//here we should already have high priority, for time precision
589
	while(1) {
590
591
		//estimate how much the controlled process is using the cpu in its working interval
592
		struct cpu_usage cu;
593
		if (compute_cpu_usage(pid,workingtime,&cu)==-1) {
594
			fprintf(stderr,"Process %d dead!\n",pid);
595
			if (lazy) exit(2);
596
			//wait until our process appears
597
			goto wait_for_process;		
598
		}
599
600
		//cpu actual usage of process (range 0-1)
601
		float pcpu=cu.pcpu;
602
		//rate at which we are keeping active the process (range 0-1)
603
		float workingrate=cu.workingrate;
604
605
		//adjust work and sleep time slices
606
		if (pcpu>0) {
607
			twork.tv_nsec=min(period*limit*1000/pcpu*workingrate,period*1000);
608
		}
609
		else if (pcpu==0) {
610
			twork.tv_nsec=period*1000;
611
		}
612
		else if (pcpu==-1) {
613
			//not yet a valid idea of cpu usage
614
			pcpu=limit;
615
			workingrate=limit;
616
			twork.tv_nsec=min(period*limit*1000,period*1000);
617
		}
618
		tsleep.tv_nsec=period*1000-twork.tv_nsec;
619
620
		//update average usage
621
		pcpu_avg=(pcpu_avg*i+pcpu)/(i+1);
622
623
		if (verbose && i%10==0 && i>0) {
624
			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);
625
		}
626
627
		if (limit<1 && limit>0) {
628
			//resume process
629
			if (kill(pid,SIGCONT)!=0) {
630
				fprintf(stderr,"Process %d dead!\n",pid);
631
				if (lazy) exit(2);
632
				//wait until our process appears
633
				goto wait_for_process;
634
			}
635
		}
636
637
		clock_gettime(CLOCK_REALTIME,&startwork);
638
		nanosleep(&twork,NULL);		//now process is working	
639
		clock_gettime(CLOCK_REALTIME,&endwork);
640
		workingtime=timediff(&endwork,&startwork);
641
642
		if (limit<1) {
643
			//stop process, it has worked enough
644
			if (kill(pid,SIGSTOP)!=0) {
645
				fprintf(stderr,"Process %d dead!\n",pid);
646
				if (lazy) exit(2);
647
				//wait until our process appears
648
				goto wait_for_process;
649
			}
650
			nanosleep(&tsleep,NULL);	//now process is sleeping
651
		}
652
		i++;
653
	}
654
655
}
(-)cpulimit/work/cpulimit-1.4/cpulimit.c.orig (+619 lines)
Line 0 Link Here
1
/**
2
 * This program is licensed under the GNU General Public License,
3
 * version 2. A copy of the license can be found in the accompanying
4
 * LICENSE file.
5
 *
6
 **********************************************************************
7
 *
8
 * Simple program to limit the cpu usage of a process
9
 * If you modify this code, send me a copy please
10
 *
11
 * Author:  Angelo Marletta
12
 * Date:    26/06/2005
13
 * Version: 1.1
14
 *
15
 * Modifications and updates by: Jesse Smith
16
 * Date: May 4, 2011
17
 * Version 1.2
18
 *
19
 */
20
21
22
#include <getopt.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <time.h>
26
#include <sys/time.h>
27
#include <unistd.h>
28
#include <sys/types.h>
29
#include <signal.h>
30
#include <sys/resource.h>
31
#include <string.h>
32
#include <dirent.h>
33
#include <errno.h>
34
#include <string.h>
35
#include <limits.h>    // for compatibility
36
37
38
//kernel time resolution (inverse of one jiffy interval) in Hertz
39
//i don't know how to detect it, then define to the default (not very clean!)
40
#define HZ 100
41
42
//some useful macro
43
#define min(a,b) (a<b?a:b)
44
#define max(a,b) (a>b?a:b)
45
46
//pid of the controlled process
47
int pid=0;
48
//executable file name
49
char *program_name;
50
//verbose mode
51
int verbose=0;
52
//lazy mode
53
int lazy=0;
54
// is higher priority nice possible?
55
int nice_lim;
56
57
//reverse byte search
58
void *memrchr(const void *s, int c, size_t n);
59
60
//return ta-tb in microseconds (no overflow checks!)
61
inline long timediff(const struct timespec *ta,const struct timespec *tb) {
62
    unsigned long us = (ta->tv_sec-tb->tv_sec)*1000000 + (ta->tv_nsec/1000 - tb->tv_nsec/1000);
63
    return us;
64
}
65
66
int waitforpid(int pid) {
67
	//switch to low priority
68
	// if (setpriority(PRIO_PROCESS,getpid(),19)!=0) {
69
        if ( (nice_lim < INT_MAX) && 
70
             (setpriority(PRIO_PROCESS, getpid(), 19) != 0) ) {
71
		printf("Warning: cannot renice\n");
72
	}
73
74
	int i=0;
75
76
	while(1) {
77
78
		DIR *dip;
79
		struct dirent *dit;
80
81
		//open a directory stream to /proc directory
82
		if ((dip = opendir("/proc")) == NULL) {
83
			perror("opendir");
84
			return -1;
85
		}
86
87
		//read in from /proc and seek for process dirs
88
		while ((dit = readdir(dip)) != NULL) {
89
			//get pid
90
			if (pid==atoi(dit->d_name)) {
91
				//pid detected
92
				if (kill(pid,SIGSTOP)==0 &&  kill(pid,SIGCONT)==0) {
93
					//process is ok!
94
                                        if (closedir(dip) == -1) {
95
                                           perror("closedir");
96
                                           return -1;
97
                                        }
98
					goto done;
99
				}
100
				else {
101
					fprintf(stderr,"Error: Process %d detected, but you don't have permission to control it\n",pid);
102
				}
103
			}
104
		}
105
106
		//close the dir stream and check for errors
107
		if (closedir(dip) == -1) {
108
			perror("closedir");
109
			return -1;
110
		}
111
112
		//no suitable target found
113
		if (i++==0) {
114
			if (lazy) {
115
				fprintf(stderr,"No process found\n");
116
				exit(2);
117
			}
118
			else {
119
				printf("Warning: no target process found. Waiting for it...\n");
120
			}
121
		}
122
123
		//sleep for a while
124
		sleep(2);
125
	}
126
127
done:
128
	printf("Process %d detected\n",pid);
129
	//now set high priority, if possible
130
	// if (setpriority(PRIO_PROCESS,getpid(),-20)!=0) {
131
        if ( (nice_lim < INT_MAX) &&
132
             (setpriority(PRIO_PROCESS, getpid(), nice_lim) != 0) ) {
133
		printf("Warning: cannot renice.\nTo work better you should run this program as root.\n");
134
	}
135
	return 0;
136
137
}
138
139
//this function periodically scans process list and looks for executable path names
140
//it should be executed in a low priority context, since precise timing does not matter
141
//if a process is found then its pid is returned
142
//process: the name of the wanted process, can be an absolute path name to the executable file
143
//         or simply its name
144
//return: pid of the found process
145
int getpidof(const char *process) {
146
147
	//set low priority
148
	// if (setpriority(PRIO_PROCESS,getpid(),19)!=0) {
149
        if ( (nice_lim < INT_MAX) &&
150
             (setpriority(PRIO_PROCESS, getpid(), 19) != 0) ) {
151
		printf("Warning: cannot renice\n");
152
	}
153
154
	char exelink[20];
155
	char exepath[PATH_MAX+1];
156
	int pid=0;
157
	int i=0;
158
159
	while(1) {
160
161
		DIR *dip;
162
		struct dirent *dit;
163
164
		//open a directory stream to /proc directory
165
		if ((dip = opendir("/proc")) == NULL) {
166
			perror("opendir");
167
			return -1;
168
		}
169
170
		//read in from /proc and seek for process dirs
171
		while ((dit = readdir(dip)) != NULL) {
172
			//get pid
173
			pid=atoi(dit->d_name);
174
			if (pid>0) {
175
				sprintf(exelink,"/proc/%d/exe",pid);
176
				int size=readlink(exelink,exepath,sizeof(exepath));
177
				if (size>0) {
178
					int found=0;
179
					if (process[0]=='/' && strncmp(exepath,process,size)==0 && size==strlen(process)) {
180
						//process starts with / then it's an absolute path
181
						found=1;
182
					}
183
					else {
184
						//process is the name of the executable file
185
						if (strncmp(exepath+size-strlen(process),process,strlen(process))==0) {
186
							found=1;
187
						}
188
					}
189
					if (found==1) {
190
						if (kill(pid,SIGSTOP)==0 &&  kill(pid,SIGCONT)==0) {
191
							//process is ok!
192
                                                        if (closedir(dip) == -1) {
193
                                                          perror("closedir");
194
                                                          return -1;
195
                                                        }
196
							goto done;
197
						}
198
						else {
199
							fprintf(stderr,"Error: Process %d detected, but you don't have permission to control it\n",pid);
200
						}
201
					}
202
				}
203
			}
204
		}
205
206
		//close the dir stream and check for errors
207
		if (closedir(dip) == -1) {
208
			perror("closedir");
209
			return -1;
210
		}
211
212
		//no suitable target found
213
		if (i++==0) {
214
			if (lazy) {
215
				fprintf(stderr,"No process found\n");
216
				exit(2);
217
			}
218
			else {
219
				printf("Warning: no target process found. Waiting for it...\n");
220
			}
221
		}
222
223
		//sleep for a while
224
		sleep(2);
225
	}
226
227
done:
228
	printf("Process %d detected\n",pid);
229
	//now set high priority, if possible
230
	// if (setpriority(PRIO_PROCESS,getpid(),-20)!=0) {
231
        if ( (nice_lim < INT_MAX) &&
232
             (setpriority(PRIO_PROCESS, getpid(), nice_lim) != 0) ) {
233
		printf("Warning: cannot renice.\nTo work better you should run this program as root.\n");
234
	}
235
	return pid;
236
237
}
238
239
//SIGINT and SIGTERM signal handler
240
void quit(int sig) {
241
	//let the process continue if it's stopped
242
	kill(pid,SIGCONT);
243
	printf("Exiting...\n");
244
	exit(0);
245
}
246
247
//get jiffies count from /proc filesystem
248
int getjiffies(int pid) {
249
	static char stat[20];
250
	static char buffer[1024];
251
        char *p;
252
	sprintf(stat,"/proc/%d/stat",pid);
253
	FILE *f=fopen(stat,"r");
254
	if (f==NULL) return -1;
255
	p = fgets(buffer,sizeof(buffer),f);
256
	fclose(f);
257
	// char *p=buffer;
258
        if (p)
259
        {
260
	  p=memchr(p+1,')',sizeof(buffer)-(p-buffer));
261
	  int sp=12;
262
	  while (sp--)
263
		p=memchr(p+1,' ',sizeof(buffer)-(p-buffer));
264
	  //user mode jiffies
265
	  int utime=atoi(p+1);
266
	  p=memchr(p+1,' ',sizeof(buffer)-(p-buffer));
267
	  //kernel mode jiffies
268
	  int ktime=atoi(p+1);
269
	  return utime+ktime;
270
        }
271
        // could not read info
272
        return -1;
273
}
274
275
//process instant photo
276
struct process_screenshot {
277
	struct timespec when;	//timestamp
278
	int jiffies;	//jiffies count of the process
279
	int cputime;	//microseconds of work from previous screenshot to current
280
};
281
282
//extracted process statistics
283
struct cpu_usage {
284
	float pcpu;
285
	float workingrate;
286
};
287
288
//this function is an autonomous dynamic system
289
//it works with static variables (state variables of the system), that keep memory of recent past
290
//its aim is to estimate the cpu usage of the process
291
//to work properly it should be called in a fixed periodic way
292
//perhaps i will put it in a separate thread...
293
int compute_cpu_usage(int pid,int last_working_quantum,struct cpu_usage *pusage) {
294
	#define MEM_ORDER 10
295
	//circular buffer containing last MEM_ORDER process screenshots
296
	static struct process_screenshot ps[MEM_ORDER];
297
	//the last screenshot recorded in the buffer
298
	static int front=-1;
299
	//the oldest screenshot recorded in the buffer
300
	static int tail=0;
301
302
	if (pusage==NULL) {
303
		//reinit static variables
304
		front=-1;
305
		tail=0;
306
		return 0;
307
	}
308
309
	//let's advance front index and save the screenshot
310
	front=(front+1)%MEM_ORDER;
311
	int j=getjiffies(pid);
312
	if (j>=0) ps[front].jiffies=j;
313
	else return -1;	//error: pid does not exist
314
	clock_gettime(CLOCK_REALTIME,&(ps[front].when));
315
	ps[front].cputime=last_working_quantum;
316
317
	//buffer actual size is: (front-tail+MEM_ORDER)%MEM_ORDER+1
318
	int size=(front-tail+MEM_ORDER)%MEM_ORDER+1;
319
320
	if (size==1) {
321
		//not enough samples taken (it's the first one!), return -1
322
		pusage->pcpu=-1;
323
		pusage->workingrate=1;
324
		return 0;
325
	}
326
	else {
327
		//now we can calculate cpu usage, interval dt and dtwork are expressed in microseconds
328
		long dt=timediff(&(ps[front].when),&(ps[tail].when));
329
		long dtwork=0;
330
		int i=(tail+1)%MEM_ORDER;
331
		int max=(front+1)%MEM_ORDER;
332
		do {
333
			dtwork+=ps[i].cputime;
334
			i=(i+1)%MEM_ORDER;
335
		} while (i!=max);
336
		int used=ps[front].jiffies-ps[tail].jiffies;
337
		float usage=(used*1000000.0/HZ)/dtwork;
338
		pusage->workingrate=1.0*dtwork/dt;
339
		pusage->pcpu=usage*pusage->workingrate;
340
		if (size==MEM_ORDER)
341
			tail=(tail+1)%MEM_ORDER;
342
		return 0;
343
	}
344
	#undef MEM_ORDER
345
}
346
347
void print_caption() {
348
	printf("\n%%CPU\twork quantum\tsleep quantum\tactive rate\n");
349
}
350
351
void print_usage(FILE *stream,int exit_code) {
352
	fprintf(stream, "Usage: %s TARGET [OPTIONS...]\n",program_name);
353
	fprintf(stream, "   TARGET must be exactly one of these:\n");
354
	fprintf(stream, "      -p, --pid=N        pid of the process\n");
355
	fprintf(stream, "      -e, --exe=FILE     name of the executable program file\n");
356
	fprintf(stream, "      -P, --path=PATH    absolute path name of the executable program file\n");
357
	fprintf(stream, "   OPTIONS\n");
358
        fprintf(stream, "      -b  --background   run in background\n");
359
	fprintf(stream, "      -l, --limit=N      percentage of cpu allowed from 0 to 100 (mandatory)\n");
360
	fprintf(stream, "      -v, --verbose      show control statistics\n");
361
	fprintf(stream, "      -z, --lazy         exit if there is no suitable target process, or if it dies\n");
362
	fprintf(stream, "      -h, --help         display this help and exit\n");
363
	exit(exit_code);
364
}
365
366
int main(int argc, char **argv) {
367
368
	//get program name
369
	char *p=(char*)memrchr(argv[0],(unsigned int)'/',strlen(argv[0]));
370
	program_name = p==NULL?argv[0]:(p+1);
371
        int run_in_background = 0;
372
	//parse arguments
373
	int next_option;
374
	/* A string listing valid short options letters. */
375
	const char* short_options="p:e:P:l:bvzh";
376
	/* An array describing valid long options. */
377
	const struct option long_options[] = {
378
		{ "pid", required_argument, NULL, 'p' },
379
		{ "exe", required_argument, NULL, 'e' },
380
		{ "path", required_argument, NULL, 'P' },
381
		{ "limit", required_argument, NULL, 'l' },
382
                { "background", no_argument, NULL, 'b' },
383
		{ "verbose", no_argument, NULL, 'v' },
384
		{ "lazy", no_argument, NULL, 'z' },
385
		{ "help", no_argument, NULL, 'h' },
386
		{ NULL, 0, NULL, 0 }
387
	};
388
	//argument variables
389
	const char *exe=NULL;
390
	const char *path=NULL;
391
	int perclimit=0;
392
	int pid_ok=0;
393
	int process_ok=0;
394
	int limit_ok=0;
395
        struct rlimit maxlimit;
396
397
	do {
398
		next_option = getopt_long (argc, argv, short_options,long_options, NULL);
399
		switch(next_option) {
400
                        case 'b':
401
                                run_in_background = 1;
402
                                break;
403
			case 'p':
404
				pid=atoi(optarg);
405
				pid_ok=1;
406
                                lazy = 1;
407
				break;
408
			case 'e':
409
				exe=optarg;
410
				process_ok=1;
411
				break;
412
			case 'P':
413
				path=optarg;
414
				process_ok=1;
415
				break;
416
			case 'l':
417
				perclimit=atoi(optarg);
418
				limit_ok=1;
419
				break;
420
			case 'v':
421
				verbose=1;
422
				break;
423
			case 'z':
424
				lazy=1;
425
				break;
426
			case 'h':
427
				print_usage (stdout, 1);
428
				break;
429
			case '?':
430
				print_usage (stderr, 1);
431
				break;
432
			case -1:
433
				break;
434
			default:
435
				abort();
436
		}
437
	} while(next_option != -1);
438
439
	if (!process_ok && !pid_ok) {
440
		fprintf(stderr,"Error: You must specify a target process\n");
441
		print_usage (stderr, 1);
442
		exit(1);
443
	}
444
	if ((exe!=NULL && path!=NULL) || (pid_ok && (exe!=NULL || path!=NULL))) {
445
		fprintf(stderr,"Error: You must specify exactly one target process\n");
446
		print_usage (stderr, 1);
447
		exit(1);
448
	}
449
	if (!limit_ok) {
450
		fprintf(stderr,"Error: You must specify a cpu limit\n");
451
		print_usage (stderr, 1);
452
		exit(1);
453
	}
454
	float limit=perclimit/100.0;
455
	if (limit <= 0.00) // || limit >1) {
456
        {
457
		fprintf(stderr,"Error: limit must be greater than 0\n");
458
		print_usage (stderr, 1);
459
		exit(1);
460
	}
461
462
        // check to see if we should fork
463
        if (run_in_background)
464
        {
465
             pid_t process_id;
466
             process_id = fork();
467
             if (! process_id)
468
                exit(0);
469
             else
470
             {
471
                setsid();
472
                process_id = fork();
473
                if (process_id)
474
                  exit(0);
475
             }
476
        }
477
478
	//parameters are all ok!
479
	signal(SIGINT,quit);
480
	signal(SIGTERM,quit);
481
482
	if (setpriority(PRIO_PROCESS,getpid(),-20)!=0) {
483
	//if that failed, check if we have a limit 
484
        // by how much we can raise the priority
485
#ifdef RLIMIT_NICE 
486
//check if non-root can even make changes 
487
// (ifdef because it's only available in linux >= 2.6.13)
488
		nice_lim=getpriority(PRIO_PROCESS,getpid());
489
		getrlimit(RLIMIT_NICE, &maxlimit);
490
491
//if we can do better then current
492
		if( (20 - (signed)maxlimit.rlim_cur) < nice_lim &&  
493
		    setpriority(PRIO_PROCESS,getpid(),
494
                    20 - (signed)maxlimit.rlim_cur)==0 //and it actually works
495
		  ) {
496
497
			//if we can do better, but not by much, warn about it
498
			if( (nice_lim - (20 - (signed)maxlimit.rlim_cur)) < 9) 
499
                        {
500
			printf("Warning, can only increase priority by %d.\n",                                nice_lim - (20 - (signed)maxlimit.rlim_cur));
501
			}
502
                        //our new limit
503
			nice_lim = 20 - (signed)maxlimit.rlim_cur; 
504
505
		} else 
506
// otherwise don't try to change priority. 
507
// The below will also run if it's not possible 
508
// for non-root to change priority
509
#endif
510
		{
511
			printf("Warning: cannot renice.\nTo work better you should run this program as root, or adjust RLIMIT_NICE.\nFor example in /etc/security/limits.conf add a line with: * - nice -10\n\n");
512
			nice_lim=INT_MAX;
513
		}
514
	} else {
515
		nice_lim=-20;
516
	}
517
	//don't bother putting setpriority back down, 
518
        // since getpidof and waitforpid twiddle it anyway
519
520
521
522
	//time quantum in microseconds. it's splitted in a working period and a sleeping one
523
	int period=100000;
524
	struct timespec twork,tsleep;   //working and sleeping intervals
525
	memset(&twork,0,sizeof(struct timespec));
526
	memset(&tsleep,0,sizeof(struct timespec));
527
528
wait_for_process:
529
530
	//look for the target process..or wait for it
531
	if (exe!=NULL)
532
		pid=getpidof(exe);
533
	else if (path!=NULL)
534
		pid=getpidof(path);
535
	else {
536
		waitforpid(pid);
537
	}
538
	//process detected...let's play
539
540
	//init compute_cpu_usage internal stuff
541
	compute_cpu_usage(0,0,NULL);
542
	//main loop counter
543
	int i=0;
544
545
	struct timespec startwork,endwork;
546
	long workingtime=0;		//last working time in microseconds
547
548
	if (verbose) print_caption();
549
550
	float pcpu_avg=0;
551
552
	//here we should already have high priority, for time precision
553
	while(1) {
554
555
		//estimate how much the controlled process is using the cpu in its working interval
556
		struct cpu_usage cu;
557
		if (compute_cpu_usage(pid,workingtime,&cu)==-1) {
558
			fprintf(stderr,"Process %d dead!\n",pid);
559
			if (lazy) exit(2);
560
			//wait until our process appears
561
			goto wait_for_process;		
562
		}
563
564
		//cpu actual usage of process (range 0-1)
565
		float pcpu=cu.pcpu;
566
		//rate at which we are keeping active the process (range 0-1)
567
		float workingrate=cu.workingrate;
568
569
		//adjust work and sleep time slices
570
		if (pcpu>0) {
571
			twork.tv_nsec=min(period*limit*1000/pcpu*workingrate,period*1000);
572
		}
573
		else if (pcpu==0) {
574
			twork.tv_nsec=period*1000;
575
		}
576
		else if (pcpu==-1) {
577
			//not yet a valid idea of cpu usage
578
			pcpu=limit;
579
			workingrate=limit;
580
			twork.tv_nsec=min(period*limit*1000,period*1000);
581
		}
582
		tsleep.tv_nsec=period*1000-twork.tv_nsec;
583
584
		//update average usage
585
		pcpu_avg=(pcpu_avg*i+pcpu)/(i+1);
586
587
		if (verbose && i%10==0 && i>0) {
588
			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);
589
		}
590
591
		if (limit<1 && limit>0) {
592
			//resume process
593
			if (kill(pid,SIGCONT)!=0) {
594
				fprintf(stderr,"Process %d dead!\n",pid);
595
				if (lazy) exit(2);
596
				//wait until our process appears
597
				goto wait_for_process;
598
			}
599
		}
600
601
		clock_gettime(CLOCK_REALTIME,&startwork);
602
		nanosleep(&twork,NULL);		//now process is working	
603
		clock_gettime(CLOCK_REALTIME,&endwork);
604
		workingtime=timediff(&endwork,&startwork);
605
606
		if (limit<1) {
607
			//stop process, it has worked enough
608
			if (kill(pid,SIGSTOP)!=0) {
609
				fprintf(stderr,"Process %d dead!\n",pid);
610
				if (lazy) exit(2);
611
				//wait until our process appears
612
				goto wait_for_process;
613
			}
614
			nanosleep(&tsleep,NULL);	//now process is sleeping
615
		}
616
		i++;
617
	}
618
619
}

Return to bug 159732