I have to figure out how to write a programming that loops but cannot be exited using CTRL-C for 5 seconds, but after 5 seconds I can use CTRL-C to end the program. I have been reading up on system calls and what not, but I can't figure out where to start. Here are the exact instructions, if someone could point me in the right direction. Thank you.
Write a C program that uses system calls that creates a loop and cannot be killed with control C for five seconds. When it starts out it prints “I’ve started looping and can’t be killed with ^C. . .” Then every second it prints a message that says “Still looping . . .” After five seconds allow the loop to be killed with control C and display the message “I'm still looping but I can be killed with ^C ...” this is displayed every second until the user kills it.
You want to look at the signal(2) interface. When certain process-related events occur in a UNIX/Linux environment, the operating system will send a signal (essentially a software interrupt) to the process. You can "catch" a signal using the signal function to set a callback function that gets notified when the given signal occurs. For a Ctrl-C you want to look at SIGINT, but there are other signals you can handle with the same interface. As for pausing, that's easy - just use sleep() in a loop.
You can use this one.
void handler(int signo)
{
signal(SIGINT,SIG_DFL);
}
main()
{
signal(SIGINT,SIG_IGN);
signal(SIGALRM,handler);
// your code.
alarm(5);// for 5 seconds.
while(1)
{ sleep(1);
printf("your message\n");
}
}
First ignoring the SIGINT using the singal. And handler for sigalrm. so first 5 seconds ctrl+c will not work. When the sigalrm is found after the ctrl+c will work. So as per your question for particular time period ctrl+c will be stopped.
Related
I'm tring to correctly emulate sigwait(), sigwaitinfo() and sigtimedwait() for Jehanne, but I can't grasp the expected behavior when multiple signals selected by the set argument are concurrently sent to a process waiting in one of these functions.
For example, the first signal will cause the sigwaitinfo to return, filling the info argument.
But what about the second signal? As far as I can see, if the second signal is not blocked (it's not included in the process signal mask), the process should receive it, interrupting the first signal management, reducing the advantage of using these group of functions.
This makes me wonder if the set provided to these functions must always be a subset of the process signal mask or if there is simply something else I'm missing.
In other words: the Linux manual page states that
In normal usage, the calling program blocks the signals in set via a prior call to sigprocmask(2) (so that the default disposition for these signals does not occur if they become pending between successive calls to sigwaitinfo() or sigtimedwait()) and does not establish handlers for these signals.
I'd like to know it this "normal usage" is the only correct usage of this API, or there are proper use cases where the set argument contains more signals than the process signal mask.
This small code is an attempt to answer your comment, and seems to work as expected on Ubuntu
// ctrl-c handler
void cc(int s) {
static int count = 0;
printf("Entering cc %d\n", ++count);
sleep (5);
printf("Leaving cc %d\n", count);
}
int main(int argc, char **argv) {
signal(SIGINT, cc); // ctrl-c
int n = 10; // leave after 10 ctrl-c
while (n--) {
pause();
}
return 0;
}
Ctrl-C is caught and cc is executed. cc increments and prints a number, and we expect the same number to be displayed when leaving the function. If cc is reentered due to another Ctrl-C before its execution completed (sleep 5) we'd have something like
Entered cc 1
Entered cc 2
Leaving cc 2
Leaving cc 2
It's not recommended to do some I/O like printf within a signal handler, but in our tiny case there is no sharing violation, and even though we'd have some stdout buffering, the "Leaving text" would eventually be similar to the above, if cc was reentered.
But that didn't happen. Pressing another Ctrl-C while cc is sleeping does seem to have that second event pending somewhere (only 1 event seems to be kept). sleep() might have a special behavior? In that case, anyway, cc would be reentered just after the sleep, and show the unwanted behavior above.
Another notable behavior is pause() in main. If another Ctrl-C is pressed while one is "sleeping", this 2nd one is executed within the same "pause" (something like while(event) { process(event); } ; this behavior is shown by the number of Ctrl-C that have to be done to leave the program: should be 10, but it's actually 10 + number of times the key was pressed while a previous one was being processed.
Not sure that works on your system, and with any event, though.
I suppose it depends on what you mean by "correct."
The normal usage is the only sensible usage.
Abnormal use is permissible in the sense that it won't court undefined behavior. It is also pointlessly, dangerously complex. Your implementation will have some algorithm for dispatching two pending signals for a process which is sigwaiting both, SIG_IGNoring neither, and blocking at most one.* It's doubtful that that process has been designed correctly, however.
* Per POSIX-1.2008's Signal Concepts, "[t]he order in which multiple, simultaneously pending signals ... are delivered to or accepted by a process is unspecified", assuming non-realtime signals.
I got a problem in C with multiple threads and signal handlers:
The main routine calls multiple loads. Each load has its own controller. The controllers then send signals to pause and resume to their respective loads at different times.
The code of the load looks something like this:
static void signal_handler(int signo) {
/* When signal PAUSE received, get into loop until RESUME arrives */
while (signo != SIGNAL_RESUME) {
/* While in the loop, the main routine gets paused */
sigwait(signalsBetweenControllerandLoad, &signo);
}
}
int load_main() {
signal(SIGNAL_PAUSE, signal_handler);
signal(SIGNAL_RESUME, signal_handler);
while(1) {
/*calculating something */
}
}
The code works when only one load is used. But when multiple loads are running, they start to interfere sometimes. If they do so, the program just freezes at execution. But sometimes the code finishes as expected. The fewer the loads, the higher the possibility that the program works as expected.
Can someone tell me why it does not work? On research I found out that a process (and thus all its child processes) can only have one signal handler active at a time. Is this true?
EDIT: I try to reformulate my main problem: How can I pause / resume the section /*calculating something */ in load_main() at an arbitrary time when I cannot modify this section ("Black box", externally given function)?
Thank you very, very much!
From signal's man page, it mentioned that signal is per-process attribute. So in a multithreaded program, the signal handler is the same for all the threads.
You can try to use semaphore to replace the signal method that you are trying to use. For more detail, you can read the POSIX semaphore man page. It also has example code for your reference.
I'm writing a program in C which connects to a camcorder via wifi and can control zoom, start and stop recording when the user wants to execute these functions.
After the initial connect to the camcorder, I will have to send a Session Refresh Command every 5 seconds. So my idea was to start a new thread after the initial connect which sends the refresh command every 5 seconds.Something like,
while(1) {
sendRefreshCommand();
usleep(5000000);
}
Is this idea ok, or is there any other way to achieve that?
Edit: Here is my code so far to illustrate a little bit what I want to do. The user is permanently asked what he wants to do. This is for testing purposes only. Later on the zoom and recording commands will be performed by the program automatically. Parallel to asking the user the session has to be refreshed every 5 seconds.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include "camctrl.h"
extern struct conf g_Config;
void* sessionContinueThread(void *session_args){
while(1){
sessionContinue(g_Config.cam_ip);
usleep(3000000);
}
}
int main(){
int sel;
pthread_t session_thread;
void *arg2;
readConfig("config2.json");
ConnectToCam(g_Config.cam_ip);
arg2 = (void *) g_Config.cam_ip;
pthread_create( &session_thread , NULL , sessionContinueThread , arg2 );
pthread_join(session_thread,NULL);
while(1){
printf("\n[0] Zoom Tele\n");
printf("[1] Zoom Wide\n");
printf("[2] Start Recording\n");
printf("[3] Stop Recording\n");
printf("[4] Session Continue\n");
printf("[5]Stop\n");
printf("Selection: ");
scanf("%d",&sel);
switch( sel ){
case 0: zoomTele(); break;
case 1: zoomWide(); break;
case 2: RecStart(); break;
case 3: RecStop(); break;
case 4: sessionContinue(g_Config.cam_ip); break;
case 5: exit(0); break;
default: break;
}
}
return 0;
}
Generally this is OK. But there are some considerations you should think about:
You have to synchronize the access to your transmission channel in order to not get some very weird, hard to trace and reproduce effects
Don't set the timeout for the refresh command exactly to 5s, take e.g. the half or a few percent lower than 5s. Otherwise you'll possibly suffer from effects that arise from jitter. (e.g. if the timebase of your camcorder is about as accurate as the timebase of your PC, the camcorder will get the "keep alive" message after 5s + transmission time if you send the request after 5s. This would be a timeout then.
Think about introducing a gate keeper thread or object to serialize the access to your communication channel. This would give you some opportunities to optimize. For example, I could imagine, that you don't have to send the keep-alive if you just issued a command.
Don't start the thread with while(1). Hand the thread a reference to a value or an event object that allows you to signal the thread it should be terminated. This gives you the opportunity to clean up everything properly when shutting down your program.
If you want me to explain some of the considerations further, let me know.
EDIT: Further explaination to #4:
You should take care that you clean up every resource you allocate. Of course you can rely on the OS that it's possibly cleaning up threads and stuff when it throws your process out of the memory, but that's not really a good way to go.
So after you creating your thread and running your program, you should also destroy your thread when the program will exit. To do so you can of course invoke some calls that terminate the thread immediately. The downside of that is, that you can happen to leave some things (e.g. mutexes) in undefined state.
What does this mean? Imagine the thread took the mutex, was about to send something and exactly at that point in time your main thread terminates the thread. In this case your mutex might remain locked, and everyone else is unable to aquire it. (e.g. to send a session destroy command).
So the solution to avoid such things is to request the thread to terminate rather than forcing the termination from outside. The request leaves the thread the chance to cleanup things he possibly allocated or acquired and then exit. The thread requesting the other thread to terminate should wait for the other thread before exiting himself (using kind of a join function).
Your idea is looking good. You can achieve same by using alarm signal and signal handlers. Initialize a signal handler for alarm signal and rise alarm signal by passing 5 as argument. After 5 seconds your process receives a sigalarm signal and it invokes signal handler of sigalrm. In signal handler send refresh command and again raise sigalrm for 5 seconds. This loops continuously works. But thing is your main program execution is halted every time it receives a sigalrm
I'm trying to write a signal handler to catch any number of consecutive SIGINT signals and prevent the program from exiting. The program is a simple file server. The handler sets a global flag which causes the while loop accepting new connections to end, a call to pthread_exit() ensures that main lets current connections finish before exiting. It all goes like clockwork when I hit ctrl-C once but a second time exits the program immediately.
I tried first with signal():
signal(SIGINT, catch_sigint);
...
static void catch_sigint(int signo)
{
...
signal(SIGINT, catch_sigint);
}
I also tried it using sigaction:
struct sigaction sigint_handler;
sigint_handler.sa_handler = catch_sigint;
sigemptyset(&sigint_handler.sa_mask);
sigint_handler.sa_flags = 0;
sigaction(SIGINT, &sigint_handler, NULL);
Unsure how to "reinstall" this one I just duplicated this code in the handler similar to the handler using the signal() method.
Neither one of these works as I expected.
Additional info:
The program is a simple file server. It receives a request from the client which is simply a string consisting of the requested file name. It utilizes pthreads so that transfers can occur simultaneously. Upon receiving SIGINT I wish for the server to exit the while loop and wait for all current transfers to complete then close. As is, no matter how I code the signal handler a second SIGINT terminates the program immediately.
int serverStop = 0;
...
int main()
{
/* set up the server -- socket(), bind() etc. */
struct sigaction sigint_hadler;
sigint_handler.sa_handler = catch_sigint;
sigint_handler.sa_flags = 0;
sigemptyset(&sigint_handler.sa_mask);
sigaction(SIGINT, &sigint_handler, NULL);
/* signal(SIGINT, catch_sigint); */
while(serverStop == 0)
{
/* accept new connections and pthread_create() for each */
}
pthread_exit(NULL);
}
...
static void catch_sigint(int signo)
{
serverStop = 1;
/* signal(SIGINT, catch_sigint) */
}
I don't think any other code could be pertinent but feel free to ask for elaboration
On Linux, you should not have to reinstall the signal handler, using either signal (which implements BSD semantics by default) or sigaction.
when I hit ctrl-C once but a second time exits the program immediately.
That's not because your handler got reset, but likely because your signal handler is doing something it shouldn't.
Here is how I would debug this issue: run the program under GDB and
(gdb) catch syscall exit
(gdb) catch syscall exit_group
(gdb) run
Now wait a bit for the program to start working, and hit Control-C. That will give you (gdb) prompt. Now continue the program as if it has received SIGINT: signal SIGINT (this will invoke your handler). Repeat the 'Control-C/signal SIGINT' sequence again. If you get stopped in either exit or exit_group system call, see where that is coming from (using GDB where command).
Update:
Given the new code you posted, it's not clear exactly where you call pthread_exit to "ensures that main lets current connections finish before exiting". As written, your main thread will exit the loop on first Control-C, and proceed to call exit which would not wait for other threads to finish.
Either you didn't show your actual code, or the "second Control-C" is a red herring and your first Control-C takes you out already (without finishing work in other threads).
NOTE: this is largely guesswork.
I'm pretty sure that calling pthread_exit in the main thread is a bad idea. If the main thread has quit, then the OS may try to send subsequent signals to some other thread.
I recommend that instead of using pthread_exit in the main thread, you just pthread_join() all the other threads, then exit normally.
But it's also important to ensure that the other threads do not get the signals. Normally this is done with sigprocmask (or maybe more correctly pthread_sigmask, which is the same under Linux) to mask the signal out in the worker threads. This ensures that the signal is never delivered to them.
Note that to avoid race conditions, you should use pthread_sigmask in the main thread just before creating a child thread, then set the signal mask back again in the main thread afterwards. This ensures that there is no window, however small, during which a child thread can possibly get unwanted signals.
I'm not sure to understand. A signal handler should usually not re-install any signal handler (including itself), because the signal handler stays in function till another is installed. See also SA_NODEFER flag to sigaction to be able to catch the signal during its handling.
A signal handler should be short. See my answer to this question. It usually mostly sets a volatile sig_atomic_t variable.
What is not working? Don't do complex or long-lasting processing inside signal handlers.
Please show your code...
Right now I have a function connected to SIGARLM that goes off after 1 second and will re-alarm itself to go off in another second everytime. There's a test in the logic of the SIGALRM function I wrote to see if a certain timeout has been reached and when it does I need it to kill a function that's running. Does anybody know how I can do this?
I forgot to mention: in the function that needs to be killed it waits on scanf() and the function needs to die even if scanf() hasn't returned yet.
One approach that might be worth looking into is using select to poll stdin and see if any data is ready. select lets you wait for some period of time on a file descriptor, controlling when you can be interrupted and by what, and seems like it's perfect here. You could just sit in a loop waiting for up to a second, then failing gracefully if no data is available. That way, SIGALRM wouldn't need to kill the function; it would take care of that all by itself.
Not sure exactly what you're asking or what the structure of the program is. If I understand correctly: some function is running and you want to terminate it if it's been running for X time. You have a SIGALARM wake up every second and that will check the running time of the other function and do the terminate.
How do you plan to kill the function? Is it a function in the same process, or is it a separate process. Is your question how to terminate it or how to tell when it needs to be terminated?
I've done something which I believe is similar. I had a multi-threaded application with a structure which contained information about the threads I wished to monitor. The structure contained a member variable "startTime". My monitoring (SIGALARM) function had access to a list of threads. When the monitor woke up it would traverse the list, compare current time to each thread startTime and send a message to the function if it had exceeded it's allowed runtime.
Does this help at all?
You could use a (global) variable to communicate between the signal handler and the function that should be stopped. The function then would check that variable to see if it should still continue running or if it should exit.
Something line this:
volatile int worker_expired = 0;
void worker() {
while (!worker_expired) {
// ...
}
}
void sig_alrm() {
worker_expired = 1;
}
If you want the signal to terminate IO operations, you need to make sure it's an interrupting signal handler. On modern systems, system calls interrupted by signals automatically restart unless you specify otherwise. Use the sigaction function rather than the signal function to setup your signal handlers if you want control over things like this. With sigaction, unless you specify SA_RESTART, signal handlers can interrupt.
If you're using file-descriptor IO functions like read, you should now get the effects you want.
If you're using stdio functions like fscanf, getting interrupted by a signal will put the FILE into an error state that can only be cleared by clearerr, and will lose any partial input in the buffer. Interrupting signals do not mix very well with stdio unless you just want to abort all operations on the file and close it when a signal is received.
So ... to restate slightly: it isn't so much that you want to kill the function as that you want any pending i/o to terminate and the function to exit.
I would either:
use select() to periodically wake up and check a flag set by the signal handler. if the flag isn't set and there's no input pending then loop and call select() again.
i suspect that your SIGALARM handler is doing more than just checking this one timer, and so using pselect() to check for i/o OR SIGALARM is probably not an option for you. i wonder if you could grab a user defined signal, and pass that in pselect. then your alarm handler would send that user defined signal.
Regarding choice 1, if SIGALARM is waking every second then you can adjust the time that select() sleeps to be within your maximum error latency. In other words assume that the timeout occurs immediately after the call to select(), then it will take until select() wakes up to detect the flag set by the SIGALARM handler. So if select() wakes up 10 times per second then it could take up to 1/10 second to detect the setting of the "give up" flag (set by the SIGALARM handler).