Sdl/C++ Opengl Program, How to Stop Sdl from Catching Sigint

SDL/C++ OpenGL Program, how do I stop SDL from catching SIGINT

Ctrl-C at the console generates an SDL_QUIT event. You can watch for this event using SDL_PollEvent or SDL_WaitEvent, and exit (cleanly) when it is detected.

Note that other actions can generate an SDL_QUIT event (e.g. attempting to close your main window via the window manager).

Can't ctrl-c my SDL apps anymore

I've been having similar issues for a few days... and after a long and painful investigation I reached to this bug report in the NVIDIA OpenGL drivers.

The problem is that the initialization code of the NVIDIA OpenGL librariy corrupts the sigprocmask of the process. This may happen to any process that links to that library. In my case the session manager was affected, so every single process in my session inherited it.

You can check if that is your case with the following command:

$ grep SigBlk /proc/<pid>/status

The normal output should be:

SigBlk: 0000000000010000

If you instead get a big number that looks like a memory address, you have the bug.

Downgrading to 325.15-11 will solve your problems.

Child process receives parent's SIGINT

If you are generating the SIGINT with Ctrl+C on a Unix system, then the signal is being sent to the entire process group.

You need to use setpgid or setsid to put the child process into a different process group so that it will not receive the signals generated by the controlling terminal.


[Edit:]

Be sure to read the RATIONALE section of the setpgid page carefully. It is a little tricky to plug all of the potential race conditions here.

To guarantee 100% that no SIGINT will be delivered to your child process, you need to do something like this:

#define CHECK(x) if(!(x)) { perror(#x " failed"); abort(); /* or whatever */ }
/* Block SIGINT. */
sigset_t mask, omask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
CHECK(sigprocmask(SIG_BLOCK, &mask, &omask) == 0);

/* Spawn child. */
pid_t child_pid = fork();
CHECK(child_pid >= 0);
if (child_pid == 0) {
/* Child */
CHECK(setpgid(0, 0) == 0);
execl(...);
abort();
}
/* Parent */
if (setpgid(child_pid, child_pid) < 0 && errno != EACCES)
abort(); /* or whatever */
/* Unblock SIGINT */
CHECK(sigprocmask(SIG_SETMASK, &omask, NULL) == 0);

Strictly speaking, every one of these steps is necessary. You have to block the signal in case the user hits Ctrl+C right after the call to fork. You have to call setpgid in the child in case the execl happens before the parent has time to do anything. You have to call setpgid in the parent in case the parent runs and someone hits Ctrl+C before the child has time to do anything.

The sequence above is clumsy, but it does handle 100% of the race conditions.

How to prevent a process opened with popen() in C++ from receiving SIGINT signal?

popen(3) is running a new shell /bin/sh -c on the command string.

The trap builtin of the shell is handling signals; with an empty first argument it is ignoring it. So you could do

 FILE* f = popen("trap '' TERM INT; gnuplot", "w");

BTW, POSIX trap requires the signals to be named without SIG prefix.

But that won't work, since gnuplot itself is explicitly handling signals. There is no way to avoid that outside of gnuplot. But take advantage of the free software nature of gnuplot: download its source code, study it, and patch it to fit your bizarre needs. FWIW, SIGINT and signal appear in several places in the source code of gnuplot-5.0.5.

However, you should consider (instead of using popen) to call the low level system calls explicitly (fork, execve, pipe, dup2, waitpid, signal ...). Read Advanced Linux Programming for details.


I strongly suspect that your question is an XY problem. You don't explain what "unfavorable effect" you actually want to avoid, and I am guessing you might avoid it otherwise.

I plot using the plot '-' command and iterate through all the values I want to plot. If the gnuplot receives SIGINT in the middle, it might stop plotting in the middle without completing the entire plot. I want it to complete the entire plot.

Actually you might set up two or three pipes (one for input, one for output, perhaps one for stderr, as seen on gnuplot side) for gnuplot. You need to go the low level system calls (explicit calls to pipe(2), fork(2) etc etc...). Your program should then have some event loop (probably based upon poll(2)...). And you would send a print "DONE" command to gnuplot after every plot '-' (don't forget to initialize with the appropriate set print '-' or have another pipe for the stderr of gnuplot). Your event loop would then catch that DONE message to synchronize. Read also this.

C in mac, about signal and flag from handler in loop different behavior on different device

I know it, I didn't reset the signal(). Why nobody tell me.

void sigint(int sig){
flag=1;
signal(SIGINT, sigint);
}

Problems interrupting capture with libpcap

signal requires a function pointer, you are using a member function pointer. Just declare Capture::terminate_process(int) as static:

class Capture {
public:
/* ... */
static void Capture::terminate_process(int s);
/* ... */
};

void Capture::terminate_process(int s){
pcap_breakloop(descr);
pcap_close(descr);
}
/* ... */
signal(SIGINT, &Capture::terminate_process);

You will have to make some changes to your code so that you don't depend on instance variables though.

Cannot draw a triangle in OpenGL

I ran some checking on your code. A few things that are wrong:

  • You are not requesting a core profile
  • You don't check your linkage
  • You are abusing the comma operator
  • You don't enable glewExperimental
  • You don't clear your depth bit

Here's the diff from yours with context (from a modified version, since you didn't include headers or defines):

@@ -22,6 +22,7 @@

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
@@ -43,6 +44,7 @@
return -1;
}

+ glewExperimental = GL_TRUE;
GLenum glewInitResult = glewInit();
if (glewInitResult != GLEW_OK)
{
@@ -69,10 +71,10 @@
rewind( fp );

code = calloc( 1, sz+1 );
- if( !code ) fclose(fp),fputs("memory alloc fails",stderr),exit(1);
+ if( !code ) {fclose(fp);fputs("memory alloc fails",stderr);exit(1);}

if( 1!=fread( code , sz, 1 , fp) )
- fclose(fp),free(code),fputs("entire read fails",stderr),exit(1);
+ {fclose(fp);free(code);fputs("entire read fails",stderr);exit(1);}

fclose(fp);
char *dot = strrchr(filename, '.');
@@ -122,6 +124,10 @@
float vertices[] = {0.0, 0.5,
0.5, -0.5,
-.5, -0.5};
+ GLuint vao;
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
@@ -160,7 +166,7 @@
}

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glDrawArrays(GL_TRIANGLES, 0, 3);

And the result: triangle



Related Topics



Leave a reply



Submit