mikeizbicki / ucr-cs100

open source software construction course
Other
485 stars 407 forks source link

Sigaction #1626

Closed kluu006 closed 9 years ago

kluu006 commented 9 years ago

When I use sigaction for ^C and ^Z, it will remove stdin and break the program. I used signal instead to see if I would have the same problem and I didn't. What is sigaction doing differently than signal?

ChannelJuanNews commented 9 years ago

I have this same issue. When I use sigaction to call my sighandler function, it goes to the function and I have it output some text so I know it works, but after it returns it just sends my while loop into an infinite loop and just prints out the prompt without stopping to get input from the user like it normally would. In other words it breaks my getline and just prints out the prompt a million times, is there something we should be doing with sigaction to prevent it from interfering with stdin? or should we just use signal like kenny did?

screen shot 2015-05-26 at 9 09 02 am

mikeizbicki commented 9 years ago

I want you to use sigaction. It is never correct to use signal in a real program.

It's possible to recreate the behavior you are seeing with signal by using sigaction. sigaction just takes a lot more parameters that specify the behavior in detail. You need to figure out what the correct parameters are to sigaction.

You're not allowed to discuss these parameters in person. This violates the collaboration policy. But I will let you discuss the parameters in this thread.

ChannelJuanNews commented 9 years ago

Yo kenny check it. I was digging around the man pages (thank God for the man pages), as well as lurking around the deep web (aka stackoverflow) and I read that a strange behavior occurs when you use getline combined with signals. Since getline see man page here depends on the read syscall, per the wikipedia (as T-Payne would say) it says here that getline might be interrupted by a signal. So the simple solution to avoid the infinite loop that we both keep getting is by simply writing cin.clear() at the beginning of the loop before any output/input happens (at least that's what I did). I'm not really sure what it did so I read this stackoverflow question and it says that cin.clear() basically clears all the error flags on cin so you can use it without interruption from error flags that usually go up when using certain signals like SIGINT and SIGTSTP. If you want to read more on why check here and if you want to see an example of the solution check here

As per the wikipedia screen shot 2015-05-26 at 12 59 31 pm

As to fixing certain parameters like Mike says, I looked at the man page for sigaction and it's really confusing trying to figure out how to use all the stuff inside the sigaction struct. I'm not sure if Mike cares if we simply ignore the error flags or if he wants us to use the parameters inside of the struct. But either way my solution works... maybe not the best/most correct way haha, but it works.

ZhuLeon commented 9 years ago

I have this exact same problem. Is the fix suggested by jruel006 okay to use? Would there be any problems with it? It seems to work for me so far.

hzhu007 commented 9 years ago

@ZhuLeon jruel006's method works well to me. But here comes another problem that when using ctr+c to interrupt a running program, it will print something like wait(): Interrupted system call. I am still trying to figure it out.

ChannelJuanNews commented 9 years ago

@ZhuLeon yeah I have the same problem. My program only gives me that error when I launch a program like cat and then have user input. When I use ^C during the use of cat it gives me same error you described. Take a look screen shot 2015-05-27 at 1 06 11 am

However the only (easy) solution I could think of was to close stderr in my sighandler function. It does the same thing but this time it doesn't print out the error. I'm not sure (again haha) if this is the best/most correct way, but (again haha) it works.

Take a look screen shot 2015-05-27 at 1 04 32 am

markasfour commented 9 years ago

@jruel006 You don't want to close stderr because you'd actually want to output error messages if an error does occur. Also, if you run ps after you do ^C, you will get the following output:

    PID TTY          TIME CMD
  6718 pts/5    00:00:00 bash
 12121 pts/5    00:00:00 rshell
 12126 pts/5    00:00:00 cat <defunct>
 12129 pts/5    00:00:00 ps

cat still exists as a process so the actual problem you are addressing isn't solved but is more concealed.

To fix this, you need to change the way your parent process waits for the child.

This stackoverflow response does a good job at explaining what needs to be done.

Essentially, we should be adding a check for EINTR. There's more info on EINTR in the signal man page.

Now after adding those additional lines, if we run ps we will see cat has been killed successfully and no wait error message is displayed:

    PID TTY          TIME CMD
  6718 pts/5    00:00:00 bash
 14210 pts/5    00:00:00 rshell
 13219 pts/5    00:00:00 ps
mikeizbicki commented 9 years ago

@markasfour's solution is excellent. +3 pts extra credit.