Does make any sense using cleanup code after an infinite loop? - c

I'm reading code for a linux daemon and its main() function is structured like this:
int main(int argc, char **argv){
// code which spawns some worker threads, sets up some
// signal handlers for clean termination, etc.
// ...
for(;;){ sleep(1); }
p_clean_exit();
return 0;
}
As it stands this makes no sense to me.
The for loop will keep the process alive, waking every sencond, then going back to sleep.
p_clean_exit() wil never be called nor 0 will be returned from the last statement.
Of course there's code elsewhere which sends signals, and and installed handlers which in turn call p-clen_exit() on their own for program termination. But this one instance here will never be reached. Right?
Does this make actual sense under some circumstance?

Does this make actual sense under some circumstance?
None of the code in your example really makes much sense: there's no point in writing a daemon that wakes up once per second only to sleep again without doing anything. But it's okay, because this is just a sample... it's the skeleton of a daemon, and it's understood that you'll add code inside that loop that does something interesting. The code that you add might call break or otherwise cause the loop to exit, and that's when it's good form to call p_clean_exit().
So yes, it's true that if you were to compile and run the code as is, the call to p_clean_exit() won't mean much. But no, it's not pointless to have it there, because the whole point of the code isn't to use it as is, it's to show you how to structure a real daemon, and a real daemon should absolutely clean up after itself.

Does this make actual sense under some circumstance?
Yes, there are function macros in C and there is Duff's case machine and setjmp function call in C. There may be a call to setjmp above that executes a switch and "jumps over" the endless loop to execute cleanup code, when a longjmp is executed from some code running concurrently to the main thread.
#define p_clean_init(context) switch (setjmp(context)) { case 0:
#define p_clean_exit() case 1: }
jmp_buf context;
int signal_handler(...) {
siglongjmp(context, 1);
}
int main() {
signal(..., signal_handler);
p_clean_init(context);
for(;;){ sleep(1); }
p_clean_exit();
}
There are pthread_cleanup_push and pthread_cleanup_pop functions that are used in a similar fashion - and from documentation we know that POSIX.1 permits pthread_cleanup_push() and pthread_cleanup_pop() to be implemented as macros that expand to text containing '{' and '}'. You may explore it's glibc implementation.
Maybe worth noting: by expanding macros to a switch(...) (but also to goto with labels as values GCC extension) is explored by pthreadthread project, the method used most notably by Contiki OS. But it would not work here unless the endless loop would yield periodically.

Related

How to use exit() safely from any thread

According to the man page (2) the exit function is not thread safe : MT-Unsafe race:exit, this is because this function tries to clean up resources (flush data to the disk, close file descriptors, etc...) by calling callbacks registered using on_exit and atexit. And I want my program to do that ! (one of my thread keeps a fd open during the whole program's lifespan so _exit is not an option for me because I want all the data to be written to the output file)
My question is the following : if I'm being careful and I don't share any sensible data (like a fd) between my threads, is it "acceptable" to call exit in a multi-threaded program ? Note that I'm only calling exit if an unrecoverable error occurs. Yet, I can't afford having a segfault while the program tries to exit. The thing is, an unrecoverable error can happen from any thread...
I was thinking about using setjmp/longjmp to kill my threads "nicely" but this would be quite complex to do and would require many changes everywhere in my code.
Any suggestions would be greatly appreciated. Thanks ! :)
EDIT : Thanks to #Ctx enlightenment, I came up with the following idea :
#define EXIT(status) do { pthread_mutex_lock(&exit_mutex); exit(status); } while(0)
Of course the exit_mutex must be global (extern).
The manpage states that
The exit() function uses a global variable that is not protected, so it is not thread-safe.
so it won't help, if you are being careful in any way.
But the problem documented is a race condition: MT-Unsafe race:exit
So if you make sure, that exit() can never be called concurrently from two threads, you should be on the safe side! You can make this sure by using a mutex for example.
A modern cross-platform C++ solution could be:
#include <cstdlib>
#include <mutex>
std::mutex exit_mutex;
[[noreturn]] void exit_thread_safe(const int status)
{
exit_mutex.lock();
exit(status);
}
The mutex ensures that exit is never called by 2 (or more) different threads.
However, I still question the reason behind even caring about this. How likely is a multi-threaded call to exit() and which bad things can even realistically happen?
EDIT:
Using std::quick_exit avoids the clang diagnostic warning.
It can't be done: even if no data is shared between threads at first, data must be shared between a thread and its cleanup function. The function should run only after the thread has stopped or reached a safe point.

C: Terminate a called function that is stuck in infinite loop from main

Let's assume I've got the following main in a c file
int f();
int main(){
//terminate f() if in infinite loop
return f();
}
and then a separate c file that could potentially hold the following:
int f() {
for(;;) {}
return 0;
}
Is there any way to detect that the function f() is in an infinite loop and terminate it's execution from within the main function?
EDIT:
I need this functionality as I am writing a testbench where the function called could potentially have an infinite loop - that's what I am checking for in the end. Therefore, I cannot modify f() in anyway. I'm also in a Linux environment.
No, there is no way to definitively determine if a function contains an infinite loop.
However, we can make a few assumptions to detect a potential infinite loop and exit a program gracefully within the program (e.g. we don't have to press Ctrl+C). This method is common in several testing frameworks used in JS. Basically, we set some arbitrary time limit for a function to complete in. If the function does not complete within that time limit, we assume it will not complete and we throw an error.
In C/C++ you could implement this with pthreads if you're on a Unix system. In Windows, you would use windows.h. I only have experience with pthreads, so I'll show a simple example of how you might get this working using pthreads.
#include <pthread.h> // Load pthread
#include <signal.h> // If f() does not exit, we will need this library to send it a signal to kill itself.
#include <stdbool.h> // You could use an int or char.
#include <stddef.h> // Defines NULL
#include <unistd.h> // Defines sleep()
bool testComplete; // Has the test completed?
/**
* The function being tested.
*/
void f() {
while(true);
}
/**
* This method handles executing the test. This is the function pthread will
* use as its start routine. It takes no arguments and returns no results.
* The signature is required for pthread_create().
*/
void *runTest(void *ptr) {
testComplete = false;
f();
testComplete = true;
}
int main() {
pthread_t testThread;
pthread_create(&testThread, NULL, runTest, NULL); // Create and start the new thread. It will begin executing runTest() eventually.
sleep(5); // Give it 5 seconds to complete (this should be adjusted or could even be made dynamic).
if(testComplete) {
// Test completed successfully.
pthread_join(testThread, NULL);
} else {
// The test did not exit successfully within the time limit. Kill it and you'll probably what to provide some feedback here.
pthread_kill(testThread, SIGPIPE); // There are other signals, but this one cannot be ignored or caught.
}
}
To compile this, you would need to execute gcc your_filename.c -o output_filename -lpthread.
If you expect the program to run on both Unix and Windows systems, you may want to consider making some unified interface for accessing threads and then adapting the OS-specific interfaces to your interface. It will make things a little simpler, especially when expanding this library.
You could call f() in a different thread and have main time-out f() when it reaches a certain limit. However, I don't think this is practical and you should really work on solving the infinite loop first.
On a Posix system (Linux, MacOS) you can schedule an alarm in the future with setitimer() before calling the function. Signal SIGALRM will be delivered to the process after the specified delay. Make sure that your program has the signal handler, you should register it with sigaction() before starting the timer.
When the signal handler takes control after the signal is raised, you may get out if the offending loop with setjmp() and longjmp().
If you call f() the way you showed (from main) then at that point the main context is in f, not main and therefore you cannot "check f from main".
What you can try is calling f() from a separate thread and check whether that thread has finished within specified time limit. However I'm not sure about practicality of this. While I don't know what you really plan to do in that function, n some cases you may stop this function from executing at the point where it did soemthing that requires cleaning up. One example that comes to mind is it calling malloc but but being able to call free at the point where you interrupt it.
Honestly, if there's a certain requirement about the time in which given function has to finish, just put that check within the function itself and return false to indicate it didn't finish successfully.

C goto different function

I'm working with an embedded system where the exit() call doesn't seem to exist.
I have a function that calls malloc and rather than let the program crash when it fails I'd rather exit a bit more gracefully.
My initial idea was to use goto however the labels seem to have a very limited scope (I'm not sure, I've never used them before "NEVER USE GOTO!!1!!").
I was wondering if it is possible to goto a section of another function or if there are any other creative ways of exiting a C program from an arbitrary function.
void main() {
//stuff
a();
exit:
return;
}
void a() {
//stuff
//if malloc failed
goto exit;
}
Thanks for any help.
Options:
since your system is non-standard (or perhaps is standard but non-hosted), check its documentation for how to exit.
try abort() (warning: this will not call atexit handlers).
check whether your system allows you to send a signal to yourself that will kill yourself.
return a value from a() indicating error, and propagate that via error returns all the way back to main.
check whether your system has setjmp/longjmp. These are difficult to use correctly but they do provide what you asked for: the ability to transfer execution from anywhere in your program (not necessarily including a signal/interrupt handler, but then you probably wouldn't be calling malloc in either of those anyway) to a specific point in your main function.
if your embedded system is such that your program is the only code that runs on it, then instead of exiting you could call some code that goes into an error state: perhaps an infinite loop, that perhaps flashes an LED or otherwise indicates that badness has happened. Maybe you can provoke a reboot.
Why dont you use return values
if malloc failed
return 1;
else
return 0;
...........
if(!a())
return;
goto cannot possibly jump to another function.
Normally, you are advised please don't use goto! In this case what you are asking is not possible.
How to deal with this? There are few solutions.
Check return code or value of problematic functions and act accordingly.
Use setjmp/longjmp. This advice should be considered even more evil than using goto itself, but it does support jumping from one function to another.
Embedded systems rarely have any variation of exit(), as that function doesn't necessarily make any sense in the given context. Where does the controller of an elevator or a toaster exit to?
In multitasking embedded systems there could be a system call to exit or terminate a process, leaving only an idle process alive that does simply a busy loop: while (1); or in some cases call a privileged instruction to go to power saving mode: while (1) { asm("halt") };
In embedded systems one possible method to "recover" from error is to asm("trap #0"); or any equivalent of calling an interrupt vector, that implements graceful system shutdown with dumping core to flash drive or outputting an error code to UART.

A function that use global variable but exit, should still be avoided in signal handlers ?

As I studied something about unix programming with C, I've learned that functions that fails to be reentrant should be avoided inside a signal handler, but if I've something like:
int main(int argc, char** argv){
...
fileFd=open(...)
signal(SIGUSR1, signalHandler)
...
}
void signalHandler(int signo){
switch(signo){
case SIGUSR1:
myExit(EXIT_FAILURE);
break;
default:
break;
}
}
Where myExit is
void myExit(int ret){
...DO STUFF...
close(fileFd);
exit(ret);
}
and fileFd is a global variable, and if I remember correctly that makes of myExit a non-reentrant... but it's still a problem to use it in a signal handler even if it will cause the exit of the program ?
Thanks, any help is appreciated and sorry if it's a dumb question.
The only thing you can do safely in a signal handler is to set a volatile sig_atomic_t variable. Please do all your handling in the main loop of your program by checking that a signal has been received (outside of the signal handler). If you do have to start doing non-portable things then consider at least using _Exit() or _exit(). Certain C libraries will guarantee that certain functions are signal-safe but this is not guaranteed to work on different systems obviously.
It might get a problem depending on "...DO STUFF...". If the stuff done there may not be done twice (like freeing the same pointer), it could crash.
In your particular case however this will probably not be a problem, if close(fileFD) is the only thing affecting global state and your file access API allows double-closing of files.
Still not safe if you use any async-unsafe functions. An asynchronous signal like USR1 can occur between any two instructions in your program, including in the middle of a critical section (locked section) in some library code.
So, for example, if the interruption happens in the middle of malloc, calling free in your signal handler (e.g. to clean up) will deadlock.

What to do when waiting for a event to finish

gcc 4.4.3 c89
I have a event loop that runs in a separate thread.
My design is like this below, just sample code to help explain.
I need to somehow wait for the initialization to complete before I can make a call to the get_device_params.
I did put a usleep for 3 seconds just before the call to the get_device_params, but I don't really want to block.
Many thanks for any suggestions,
void* process_events(void *data)
{
switch(event_type)
{
case EVT_INITIALIZED:
/* Device is now initialized */
break;
}
}
int main(void)
{
/* Create and start thread and process incoming events */
process_events();
/* Initialize device */
initialize_device();
/* Get device parameters */
/* However, I cannot run this code until initialization is complete */
get_device_params();
return 0;
}
If this separate thread is a POSIX thread (i.e. you're on a typical UNIX platform), then you can use pthread conditional variables.
You call pthread_cond_wait() in the waiting thread. When the init thread finishes its work, you call pthread_cond_signal(). In my opinion that's a canonical way to wait for initialization in another thread.
I need to somehow wait for the initialization to complete before I can make a call to the get_device_params.
Since you apparently have some sort of a FSM inside the process_events(), and it why ever runs in a separate thread, you shouldn't do anything from the main thread with the device.
In other words, logically, call to the get_device_params(); should be placed inside the FSM, on the event that the device is initialized EVT_INITIALIZED which I presume is triggered by the initialize_device().
Alternatively, you can create second FSM (possibly in another thread) and let the process_events() (the first FSM) after it has finished its own processing, forward the EVT_INITIALIZED event to the second FSM. (Or initialize_device() could send the event to the both FSMs simultaneously.)
To me it seems (from the scarce code you have posted) that your problem is that you try to mix sequential code with an event based one. Rule of thumb: in event/FSM based application all code should run inside the FSM, being triggered by an event; there should be no code which may run on its own outside of the FSM.
If it were me, I would probably use a barrier. In main you can call pthread_barrier_init, indicating that you have 2 threads. Then, in main call pthread_barrier_wait, to wait on the barrier you initialized, after calling your device initialization function. Finally, in the device thread, after you initialize your device, you can call pthread_barrier_wait on the same barrier and when both threads are waiting, the barrier will have been satisfied, so both threads will continue. I find barriers easier to use than condition variables sometime, but I'm sure that's an issue of preference.

Resources