First off, this IS a homework assignment for an operating systems class, but the question isn't "how do i do the assignment" but "why is my particular implementation not working".
I've searched the forums here, but could not find anything particular to my problem, Googling and the linux manual pages haven't been much help either.
What the program is supposed to do is create a very simple shell (that sits atop the already running shell) to parse commands and run them via a child process, with an option to run in the background. The program is also to implement a history feature that displays the last 10 commands, and provide a shortcut for the user to quickly select one of these commands and execute it.
Here is the problem, the assignment specifically requires that the recent command list be displayed with <ctrl><c>. the code i am using to accomplish this is roughly
Expand|Select|Wrap|Line Numbers
- struct sigaction sigint_handler; //global
- void display_history()
- {
- // msg is a globally defined c-string that says "caught <ctrl><c>"
- write(STDOUT_FILENO,msg,strlen(msg)); //signal safe ouput
- }
- int main(void)
- {
- sigint_handler.sa_handler = display_history;
- //register display_history() to replace default SIGINT action
- sigaction(SIGINT,&sigint_handler,NULL);
- while(1)
- { //parser detects C - d to exit program normally
- parser(iBuffer,args); //parses commands and arguments, storing
- //this in the two memories passed by ref.
- switch(fork())
- {
- case 0: execvp(iBuffer,args);
- break;
- case -1: handle_error();
- break;
- default:
- if(background == 0) //if "run in background" option not
- wait(NULL); //selected, wait for child to complete
- }
- }
- }
the first time C- c is pressed, the message displays correctly. The second time C-c is pressed (either immediately or after executing a few commands) the message is printed twice, the third time C- c is pressed the message is printed 3 times etc.
This multiple calling of the display_hist function when C - c is pressed is what has me confused. To make matters worse, gdb seems to catch the SIGINT itself sometimes, exiting the debugger, making debugging this problem difficult. Perhaps the most confusing bit is that the problem doesnt always act the same way, sometimes gdb catches sigint, sometimes it doesnt. Sometimes the program catches sigint and displays the stub message more then once on the very first C -c. Sometimes the number of times that the stub message is displayed is twice the C-c press, i.e on the nth usage of C - c, the stub is printed 2*n times.
I have tried:
-setting sa_flags on the sigaction struct to SA_RESTART
-using sigprocmask() to Block sigint signals, set default SIGINT action
to ignore, then unblock sigint so that any enqueued signals will be
de-queued and ignored, (since the error looks like some queue of signal
is being dequeued). This blocking was performed in the display_hist
(signal handling) function - i would have like to have tried this in the main
code, but am not sure how to use it since i don't think you can be sure
at what point the process will recieve the signal.
ANY insight into signal handling would be most appreciated, as this problem has
plagued me for a few days now. I'm hoping that the problem is glaringly obvious.
thanks.