The problem is I'm trying to pass a message queue ID from a parent to child using execve. However, each time to do, I am able to compile it but get the error message of:
[xcb] Unknown sequence number while processing queue
[xcb] You called XInitThreads, this is not your fault
[xcb] Aborting, sorry about that.
The threads work; it's just that making a new window using execve
gives me that error. The program is meant to create another window by pressing C in the window.
compiler code:
gcc [ ].c -Wall -lX11 -pthread
code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <sys/msg.h>
#include <sys/types.h>
struct Global {
Display *dpy;
Window win;
GC gc;
int xres, yres;
} g;
struct mesg_buffer {
long type;
char text[100];
} mymsg;
int done = 0;
void x11_cleanup_xwindows(void);
void x11_init_xwindows(void);
void x11_clear_window(void);
void check_mouse(XEvent *e);
int check_keys(XEvent *e);
void render(void);
int mqid;
int myargc;
char **myargv;
char **myenvp;
void *Thread(void *arg){
return (void *)0;
}
int main(int argc, char *argv[], char *envp[])
{
myargc = argc;
myargv = argv;
myenvp = envp;
XEvent e;
int countdown = 0;
int IP_check = 0;
pthread_t tid;
if (argc > 1)
countdown = atoi(argv[1]);
if (argc > 2){
if (strcmp(argv[2], "Child") == 0)
pthread_create(&tid, NULL, Thread, (void *)1);}
if (argc > 3){
mqid = atoi(argv[3]);
++IP_check;}
if(IP_check == 0)
mqid = msgget(IPC_PRIVATE, IPC_CREAT | 0666);
x11_init_xwindows();
while (!done) {
/* Check the event queue */
while (XPending(g.dpy)) {
XNextEvent(g.dpy, &e);
done = check_keys(&e);
render();
}
usleep(4000);
if (countdown > 0){
if (--countdown == 0){
done = 1;
}
}
}
x11_cleanup_xwindows();
return 0;
}
void x11_cleanup_xwindows(void)
{
XDestroyWindow(g.dpy, g.win);
XCloseDisplay(g.dpy);
}
void x11_init_xwindows(void)
{
int scr;
if (!(g.dpy = XOpenDisplay(NULL))) {
fprintf(stderr, "ERROR: could not open display!\n");
exit(EXIT_FAILURE);
}
scr = DefaultScreen(g.dpy);
g.xres = 400;
g.yres = 200;
g.win = XCreateSimpleWindow(g.dpy, RootWindow(g.dpy, scr), 1, 1,
g.xres, g.yres, 0, 0x00ffffff, 0x00000000);
XStoreName(g.dpy, g.win, "cs3600 xwin sample");
g.gc = XCreateGC(g.dpy, g.win, 0, NULL);
XMapWindow(g.dpy, g.win);
XSelectInput(g.dpy, g.win, ExposureMask | StructureNotifyMask |
PointerMotionMask | ButtonPressMask |
ButtonReleaseMask | KeyPressMask);
}
//
//Where I believe the issue happens
//removing temp from xargv[] will get it to run normally
// though I need to send temp through.
//
void make_child_win(){
char temp [50];
sprintf(temp, "%i", mqid);
int cpid = fork();
if (cpid == 0){
char *xargv[] = {myargv[0], "0" , "Child", temp};
execve(myargv[0], xargv, myenvp);
}
}
int check_keys(XEvent *e)
{
int key;
if (e->type != KeyPress && e->type != KeyRelease)
return 0;
key = XLookupKeysym(&e->xkey, 0);
if (e->type == KeyPress) {
switch (key) {
case XK_c:
make_child_win();
break;
case XK_Escape:
msgctl(mqid, IPC_RMID, NULL);
return 1;
}
}
return 0;
}
void render(void)
{
}
Transferring my comment into an answer.
You have:
char *xargv[] = {myargv[0], "0" , "Child", temp};
execve(myargv[0], xargv, myenvp);
You need a null pointer to terminate the argv passed to execve()
, so you should use:
char *xargv[] = { myargv[0], "0" , "Child", temp, 0 };
You could write NULL
instead of the bare 0
, but it makes no operational difference in this context (but there are other contexts where the difference could be significant, such as using execl()
instead of execve()
).