Why doesn't Linux prevent spawning infinite number of processes and crashing? - c

With the very simple code below, my system (Ubuntu Linux 14.04) simply crashes not even letting my mouse respond. I had to force quit with the power button. I thought Linux is a stable OS tolerable of handling such basic program errors. Did I miss something?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
void check(int isOkay){
if(!isOkay){
printf("error\n");
abort();
}
}
int main(void){
#define n 1000000
int array[n];
sem_t blocker;
int i;
while(1){
if(!fork()){
for(i = 0; i < n; ++i){
array[i] = rand();
}
check(sem_init(&blocker, 0, 0) == 0);
check(sem_wait(&blocker) == 0);
}
}
return 0;
}

Congratulations, you've discovered the fork bomb. There are shell one-liners that can wreak the same sort of havic with a lot less typing on your part.
It is in fact possible to limit the number of processes that a user can spawn using ulimit -- see the bottom of the linked wikipedia articles for details.
A desktop install of Ubuntu is not exactly a hardened server, though. It's designed for usability first and foremost. If you need a locked down system that can't crash, there are better options.

The command ulmit -u shows the maximum number of processes that you can start. However, do not start that many processes in the background: your machine would spend time switching between processes and wouldn't get around to getting actual work done.
The linux does its job of processing your request to create a process, it is for the user to implement his code based on this limit.

The main problem here is determining the best limit. A lot of software doesn't use fork() at all, so do you set the limit to something small like 5? Some software might create a new process whenever it receives a request from network, so do you set the limit to "max. number of network packets"? If you assume most software isn't buggy, then you'd be tempted to set the limit relatively high so that correct software works properly.
The other problem is one of scheduling priorities. In a well designed system things like the GUI would be "high priority" and if it wants CPU time it'd preempt normal/lower priority work immediately. If this was the case, a massive fork bomb running at normal/lower priority would have no effect on the system's ability to respond to the user, and the user would be able to kill the fork bomb without much problem.
Sadly, for a variety of reasons, the scheduler in Linux doesn't work like that. It does support priorities, but to use them you have to be a "real time" process and have to be running as root (which is a massive security disaster). Without sane priorities, Linux assumes that every forked process is as important as everything else, and the CPU/s end up busy doing the forking and there's no CPU time left to respond to the user.

Related

What is the efficient way to continuously check until a condition is true

So I have this program that continuously check until the condition is true. My problem is whenever I run it, my computer slows down because of the loop. Can anyone please suggest the best and most efficient way to do this? Thank you for your response in advance.
To illustrate my problem, here is a code that represents it:
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <windows.h>
int main(void){
time_t now;
struct tm *local;
while(1){
time(&now);
local = localtime(&now);
if(local->tm_min > 55){
printf("Time:\t%d:%d:%d\n",local->tm_hour,local->tm_min,local->tm_sec);
getch();
exit(0);
}
}
return 0;
}
If polling is really what you want, or you have to use it, then you must give breath to the system by using sleep's.
So, how much to sleep in each iteration? It can be a fixed value (and if you sleep just 1 millisecond you will be stunned at how this is effective). A fixed value, say 20-30 milliseconds is good if you check for slow events like keystrokes by a real user. If, say, you are monitoring a serial port, perhaps you need lower values.
Then, depending on the application, you can also implement a variable sleep time. For example (this is a little stupid but it is just to explain): you wait for keystrokes, and sleep 30 milliseconds. Then you use your program in a pipe and discover that it is painly slow. A solution could be to set the value to sleep equal to 30 ms, but after having read a character, the value is lowered to 0 which causes the sleep to be not performed. Every time the condition fails the value is raised up to the maximum limit (20-30 milliseconds for a keyboard).
-- EDIT AFTER COMMENTS --
It has pointed out that keyboards and serial ports do not need polling, or they should not be polled. Generally speaking this is true, but it depends on the hardware and operating system (which in turn is a piece of software and, if the hardware does not support an interrupt for a given condition, even the OS would have to poll). About keyboards, for example, I thought at those little ones implemented as a matrix of buttons: some small CPUs have special facilities to generate an interrupt on any I/O change, but other don't: in that case polling is the only solution - and it is also ideal for implementing anti-bouncing (this kind of polling is not necessarily performed inside a loop).
For serial ports, it is almost true that nobody would implement one without an interrupt (to avoid polling). But even so, it is difficult to manage the incoming data in an event-driven fashion; often a flag is set, and some other part of the program, which polls that flag, will work out the message.
Event-driven programming seems easy at first, but as soon the program gets bigger the complication augments too.
There are other situations to consider, for example loops which read data from somewhere and process those data. If something else has to be done inside the loop, for example checking how much time is passed, but the reading is blocking, the reading must be implemented in a non-blocking way, and the whole loop must turn into a kind of polling for one or more conditions -unless one uses multi-threading.
Anyway, I agree that polling is evil and should only be used when necessary.
Efficiently? One way or the other you need to put your process to sleep until the condition WILL BE TRUE - then wake up and die (so to speak :-). Since your code includes windows.h I'll assume you're running on Windows and thus have the Sleep() function available.
#include <stdio.h>
#include <windows.h>
#include <time.h>
int main(void)
{
time_t now;
struct tm *local;
DWORD msecs;
time(&now);
local = localtime(&now);
/* (55 * 60000) = msecs in 55 minutes */
msecs = (55 * 60000) - ((local->tm_min * 60000) + (local->tm_sec * 1000));
if(msecs > 0)
Sleep(msecs)
return 0;
}

C: How to check if the computer is locked/sleep?

Is there any function in C to check if the computer is going to sleep,hibernate or locked and waking up from these state?
In msdn they provided for C#, C++ but not for C.
My OS is windows7
Like below is the code I'm using to check the time duration between starting the program and terminating it(shutting down the system will terminate the program so this way time duration can be measured).
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include<time.h>
clock_t start_time=0;
void bye (void)
{
FILE *read,*write;
write=fopen("F:\\count.txt","w");
clock_t end_time=clock();
fprintf(write,"Time: %d",(end_time-start_time)/CLOCKS_PER_SEC);
fclose(write);
}
int main (void)
{
start_time=clock();
atexit (bye);
//exit (EXIT_SUCCESS);
getch();
}
In the same way I want to check for locked/sleep/hibernate.
One possible way to wrap the c++ code(provided in the link) in c as mentioned by #ddriver
But is it not possible in C at all?
The WinAPI has generally at least the same possibilities as .NET framework. What your are asking for is the PowerManagement API.
You will have to register to receive PowerSettingNotificationEvents with the RegisterPowerSettingNotification function. Unfortunately, it is used differently for a GUI application where you give a handle to a window that will then receive a WM_POWERBROADCAST message each time the system is about to change state (one of the suspend modes or the hibernate mode), and for a non GUI (typically a service) that registers a HandlerEx callback with a dwControl parameter of SERVICE_CONTROL_POWEREVENT and a dwEventType of PBT_POWERSETTINGCHANGE.
The link you provide is about signals, emitted when power mode is changing. So, obviously, you can check when the system is about to go to sleep, or it just woke up.
As of checking if the system currently sleeps, that is simply not possible, as user code will simply not be running during deep sleep states. Maybe some platform specific, very low level BIOS API, but those are usually not public, and far from portable.

How to prevent linux soft lockup/unresponsiveness in C without sleep

How would be the correct way to prevent a soft lockup/unresponsiveness in a long running while loop in a C program?
(dmesg is reporting a soft lockup)
Pseudo code is like this:
while( worktodo ) {
worktodo = doWork();
}
My code is of course way more complex, and also includes a printf statement which gets executed once a second to report progress, but the problem is, the program ceases to respond to ctrl+c at this point.
Things I've tried which do work (but I want an alternative):
doing printf every loop iteration (don't know why, but the program becomes responsive again that way (???)) - wastes a lot of performance due to unneeded printf calls (each doWork() call does not take very long)
using sleep/usleep/... - also seems like a waste of (processing-)time to me, as the whole program will already be running several hours at full speed
What I'm thinking about is some kind of process_waiting_events() function or the like, and normal signals seem to be working fine as I can use kill on a different shell to stop the program.
Additional background info: I'm using GWAN and my code is running inside the main.c "maintenance script", which seems to be running in the main thread as far as I can tell.
Thank you very much.
P.S.: Yes I did check all other threads I found regarding soft lockups, but they all seem to ask about why soft lockups occur, while I know the why and want to have a way of preventing them.
P.P.S.: Optimizing the program (making it run shorter) is not really a solution, as I'm processing a 29GB bz2 file which extracts to about 400GB xml, at the speed of about 10-40MB per second on a single thread, so even at max speed I would be bound by I/O and still have it running for several hours.
While the posed answer using threads might possibly be an option, it would in reality just shift the problem to a different thread. My solution after all was using
sleep(0)
Also tested sched_yield / pthread_yield, both of which didn't really help. Unfortunately I've been unable to find a good resource which documents sleep(0) in linux, but for windows the documentation states that using a value of 0 lets the thread yield it's remaining part of the current cpu slice.
It turns out that sleep(0) is most probably relying on what is called timer slack in linux - an article about this can be found here: http://lwn.net/Articles/463357/
Another possibility is using nanosleep(&(struct timespec){0}, NULL) which seems to not necessarily rely on timer slack - linux man pages for nanosleep state that if the requested interval is below clock granularity, it will be rounded up to clock granularity, which on linux depends on CLOCK_MONOTONIC according to the man pages. Thus, a value of 0 nanoseconds is perfectly valid and should always work, as clock granularity can never be 0.
Hope this helps someone else as well ;)
Your scenario is not really a soft lock up, it is a process is busy doing something.
How about this pseudo code:
void workerThread()
{
while(workToDo)
{
if(threadSignalled)
break;
workToDo = DoWork()
}
}
void sighandler()
{
signal worker thread to finish
waitForWorkerThreadFinished;
}
void main()
{
InstallSignalHandler;
CreateSemaphore
StartThread;
waitForWorkerThreadFinished;
}
Clearly a timing issue. Using a signalling mechanism should remove the problem.
The use of printf solves the problem because printf accesses the console which is an expensive and time consuming process which in your case gives enough time for the worker to complete its work.

how to slow down a process?

Suppose I have a program that runs in a given amount of time (say, three seconds). I want to run this program so that it runs n-times slower (specified on command line). How would you achieve it with (or better, without) changes to the program ?
please note that adding a sleep at the end is not a solution. The program has to run slower, not to run at full speed for the first three seconds and then do nothing for the remaining time. Also, using "nice" under unix is not a good solution either. it will run slower if other processes demand the processor, but at full speed if nothing is processor-demanding at the same time.
This is a curiosity question. Nothing serious to do related to it. The fact is that I remember 15-20 years ago games that were simply too fast to play on new processors, because they were timed with the processor clock. You had to turn off the turbo.
Let's assume the program is a C compiled program.
One idea is to write a 'ptrace runner.' ptrace is the call that allows you to implement a debugger on platforms such as Linux and Mac.
The idea is to attach to the program and then just repeatedly tell the application to run one instruction with ptrace(PTACE_SINGLESTEP). If that's not slow enough, you could add a sleep between each call to ptrace in the runner program.
I wrote a simple example on my linux box how to slow down a child process with SIGSTOP and SIGCONT signals:
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
void dosomething(void){
static volatile unsigned char buffer[1000000];
for(unsigned i=0;i<1000;i++) for(unsigned j=0;j<sizeof(buffer);buffer[j++]=i){;}
}
#define RUN 1
#define WAIT 1
int main(void){
int delay=0, status, pid = fork();
if( !pid ){ kill(getpid(),SIGSTOP); dosomething(); return 0; }
do{
waitpid( pid, &status, WUNTRACED | WCONTINUED );
if( WIFSTOPPED (status) ){ sleep(delay); kill(pid,SIGCONT); }
if( WIFCONTINUED(status) && WAIT ){ sleep(RUN ); kill(pid,SIGSTOP); }
delay=WAIT;
}while( !WIFEXITED(status) && !WIFSIGNALED (status) );
}
No slowdown when WAIT is zero, otherwise after every RUN seconds the parent stop the child for WAIT seconds.
Runtime results:
RUN=1 WAIT=0
---------------
real 3.905s
user 3.704s
sys 0.012s
RUN=1 WAIT=1
---------------
real 9.061s
user 3.640s
sys 0.016s
RUN=1 WAIT=2
---------------
real 13.027s
user 3.372s
sys 0.032s
cpulimit is a tool that does something like this. It works by periodically
kill -STOP and kill -CONT the process, which has the effect of it running slower (when averaged over time).
If you have DTrace you may be able to use it's chill() function. You could insert this chill at almost anyplace in a userland application and in multiple places. It's been used before to replicate race conditions seen on slower systems.
I ran some application in a virtual machine under ubuntu. It was really slow.
You could configure the virtual machine usage of the system.
You might obfuscate the situation a little further by running a virtual machine under a virtual machine under a virtual machine, ...

Change priority of the current process in C

On Windows I can do:
HANDLE hCurrentProcess = GetCurrentProcess();
SetPriorityClass(hCurrentProcess, ABOVE_NORMAL_PRIORITY_CLASS);
How can I do the same thing on *nix?
Try:
#include <sys/time.h>
#include <sys/resource.h>
int main(){
setpriority(PRIO_PROCESS, 0, -20);
}
Note that you must be running as superuser for this to work.
(for more info, type 'man setpriority' at a prompt.)
If doing something like this under unix your want to (as root) chmod you task and set the s bit. Then you can change who you are running as, what your priority is, your thread scheduling, etc. at run time.
It is great as long as you are not writing a massively multithreaded app with a bug in it so that you take over a 48 CPU box and nobody can shut you down because your have each CPU spinning at 100% with all thread set to SHED_FIFO (runs to completion) running as root.
Nah .. I wouldn't be speaking from experience ....
# allain Can you lower your own process' priority without being superuser?
Sure. Be aware, however, that this is a one way street. You can't even get back to where you started. And even fairly small reductions in priority can have startlingly large effects on running time when there is significant load on the system.

Resources