I'm exploring creating a window manager using XCB, but I've run into some troubles pretty early on. My code won't even connect to XCB with xcb_connect. I thought it was pretty straightforward, but I'm getting some really strange behavior. My code looks like this:
#include <stdio.h>
#include <xcb/xcb.h>
int i = 0;
int connect(xcb_connection_t** conn) {
xcb_connection_t* try_conn = xcb_connect(NULL, NULL);
int status = 0;
int conn_status = xcb_connection_has_error(try_conn);
if (conn_status != 0) {
i = i + 1;
switch (conn_status) {
case XCB_CONN_ERROR:
printf("Error connecting to the X Server, try %d\n", i);
break;
case XCB_CONN_CLOSED_EXT_NOTSUPPORTED:
printf("Connection closed, extension not supported\n");
break;
case XCB_CONN_CLOSED_MEM_INSUFFICIENT:
printf("Connection closed, memory insufficient\n");
break;
case XCB_CONN_CLOSED_REQ_LEN_EXCEED:
printf("Connection closed, required length exceeded\n");
break;
case XCB_CONN_CLOSED_PARSE_ERR:
printf("Connection closed, parse error\n");
break;
case XCB_CONN_CLOSED_INVALID_SCREEN:
printf("Connection closed, invalid screen\n");
break;
default:
printf("Connection failed with unknown cause\n");
break;
}
status = 1;
} else {
*conn = try_conn;
status = 0;
}
return status;
}
int main() {
xcb_connection_t* conn = NULL;
if (connect(&conn) != 0) {
printf("Error connecting to the X Server\n");
return -1;
}
return 0;
}
It prints the line that says Error connecting the the X Server, try %d\n 8191 times every time I run the program. When I looked at what was going on with gdb, it seems like every time I call xcb_connect, my code goes into this deep recursion thing (like thousands of frames deep) between xcb_connect_to_display_with_auth_info() and my connect() function.
The part that really confuses me is how xcb_connect_to_display_with_auth_info() can even call my connect() function at all, because it's from a separate library and I haven't passed in a pointer to my function. My code looks to me like it's behavior should be completely "linear", but that's not the case at all.
I'm testing the window manager by running Xephyr with the X server name :1 and setting DISPLAY to :1 before running the program.
I'm somewhat new to XCB and C itself, so I'm probably missing something blatantly obvious, but I would appreciate any pointers. I've been looking at hootwm for inspiration mostly so far.
You are overriding the C library's connect function. XCB calls that function to connect to the X11 server, but instead ends up with calling your function instead.
https://linux.die.net/man/2/connect
One possible way out of this (besides giving your function another name) is to make it static.
Related
I'm trying to create a function which uses enet to send some data, but first I wanted to make sure the example in here works correctly on the mips system.
I tested the example on Ubuntu and Mac and it works perfectly fine, but when I test it on the mips system it always fails to create the host, which is always created without any trouble on the other systems I tested. Do someone here knows what might be happening? Someone told me that it might be a problem with the libenet.so file, but since it works with the enet_initialize function, I think it might be something else.
This is my code if someone wants to check it out:
#define ENET_IMPLEMENTATION
#include <enet.h>
#include <stdio.h>
int main() {
if (enet_initialize () != 0) {
printf("An error occurred while initializing ENet.\n");
return 1;
}
else {
printf("Welcome to enet! :D\n");
}
//Client side
ENetHost* client = { 0 };
client = enet_host_create(NULL /* create a client host */,
1 /* only allow 1 outgoing connection */,
2 /* allow up 2 channels to be used, 0 and 1 */,
0 /* assume any amount of incoming bandwidth */,
0 /* assume any amount of outgoing bandwidth */);
if (client == NULL) {
fprintf(stderr,
"An error occurred while trying to create an ENet client host.\n");
exit(EXIT_FAILURE);
}
else {
printf("Client created successfully! :D\n");
}
enet_host_destroy(server);
enet_deinitialize();
return 0;
}
And my output is the messages:
Welcome to enet! :D
An error occurred while trying to create an ENet client host.
Try debugging it and stepping into the enet_host_create function to see where it's failing. It looks like the source code for that function is in the header file.
If you're not able to debug and step through it, you could temporarily modify the header file to add additional logging.
Some potential reasons it's failing:
peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID
enet_malloc malloc fails to allocate memory
net_socket_create(ENET_SOCKET_TYPE_DATAGRAM) == ENET_SOCKET_NULL
I'm thinking that it's probably not an issue with the peerCount because the default ENET_PROTOCOL_MAXIMUM_PEER_ID is 0xFFF and you're passing 1.
It may be an issue with enet_malloc or net_socket_create. By default enet_malloc is just the regular malloc from stdlib, which I'm guessing is what you're using since you're not initializing with enet_initialize_with_callbacks. And enet_socket_create just calls the socket system call:
ENetSocket enet_socket_create(ENetSocketType type) {
return socket(PF_INET6, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
}
I would make sure your platform's malloc and socket implementations are working as expected.
FINAL EDIT: Solution to problem was stated by the answer I have selected. The representative example code is shown in the diff here
EDIT: Full compile-able code at the bottom of the post.
I have this rudimentary multithreaded server that simply accepts a connection and is supposed to pass the file descriptor off to a thread to allow this thread to handle it directly until the client disconnects.
For some reason, even with the following code flow inside of the server, some clients "Fall through the cracks" and get stuck in limbo. (They never get handled by the server so they just hang after accepting the connection)
The following block is my server main running loop:
while(g_serv.b_running)
{
//printf("Awaiting connection.\n");
client_fd = accept(g_serv.serv_listener_fd,
(struct sockaddr*)&cli_addr,
&clilen);
if (0 > client_fd)
{
fprintf(stderr,
"Error accepting connection. [%s]\n",
strerror(errno));
continue;
}
err = sem_trywait(&(g_serv.client_count_sem));
if (0 > err)
{
fprintf(stderr,
"Max connections reached. [%s]\n",
strerror(errno));
notify_client_max_connections(client_fd);
close(client_fd);
client_fd = 0;
continue;
}
printf("A client has connected.\n");
char byte[2] = "0";
err = send(client_fd, byte, 1, 0);
// Set up client FD in global position and wake up a thread to grab it
//
pthread_mutex_lock(&(g_serv.new_connection_fd_lock));
g_serv.new_connection_fd = client_fd;
if (0 != g_serv.new_connection_fd)
{
pthread_cond_signal(&(g_serv.new_connection));
}
pthread_mutex_unlock(&(g_serv.new_connection_fd_lock));
}
This block is the thread handling function:
void* thread_handler(void* args)
{
serv_t* p_serv = (serv_t*)args;
bool thread_client_connected;
int thread_client_fd;
while(p_serv->b_running)
{
pthread_mutex_lock(&(p_serv->new_connection_fd_lock));
while (0 == p_serv->new_connection_fd && p_serv->b_running)
{
pthread_cond_wait(&(p_serv->new_connection),
&(p_serv->new_connection_fd_lock));
}
thread_client_fd = p_serv->new_connection_fd;
p_serv->new_connection_fd = 0;
pthread_mutex_unlock(&(p_serv->new_connection_fd_lock));
// In the case of a pthread cond broadcast for exiting the server.
//
if (0 == thread_client_fd)
{
continue;
}
thread_client_connected = true;
while (thread_client_connected)
{
thread_client_connected = handle_client(thread_client_fd);
}
close(thread_client_fd);
thread_client_fd = 0;
sem_post(&(p_serv->client_count_sem));
}
return NULL;
} /* thread_handler */
Just for data reference here is my serv_t struct:
typedef struct serv_t {
bool b_running;
int max_connections;
int serv_listener_fd;
sem_t client_count_sem;
pthread_mutex_t new_connection_fd_lock;
pthread_cond_t new_connection;
int new_connection_fd;
pthread_t* p_thread_ids;
} serv_t;
Basically, if I run netcat or a client program I have against it with multiple instances via a bash command to "background" the application, some of these instances get stuck. I have it redirecting the output to a file, but what's happening is that particular instance of the client/netcat is just getting stuck after the accept call.
More specifically, if I run my program with two threads, one instance of a program gets stuck and no subsequent copies get stuck, even running 6500 instances against the server.
If I run it with ten threads, as many as 8 or 9 instances get stuck, but the threads still function properly within the server.
EDIT:
Client code I refer to, starting from the server letting the client know that the server is ready to receive data:
char buff[2] = { 0 };
err = recv(client_socket_fd, buff, 1, 0);
if ('0' != buff[0] && 1 != err)
{
fprintf(stderr,
"Server handshake error. [%s]\n",
strerror(errno));
close(client_socket_fd);
return EXIT_FAILURE;
}
if (NULL != p_infix_string)
{
if (MAX_BUFFER_SIZE < strlen(p_infix_string))
{
fprintf(stderr,
"Infix string is over 100 characters long.\n");
return EXIT_FAILURE;
}
errno = 0;
char* p_postfix = infix_to_postfix(p_infix_string);
if (EINVAL == errno || NULL == p_postfix)
{
fprintf(stderr, "Error converting provided string.\n");
}
bool success = send_postfix(p_postfix, client_socket_fd);
free(p_postfix);
if (false == success)
{
fprintf(stderr,
"An error occured while sending the equation to the server.\n");
close(client_socket_fd);
return EXIT_FAILURE;
}
}
The client is getting stuck at the receive call here:
bool send_postfix(char* p_postfix, int client_socket_fd)
{
if (NULL == p_postfix)
{
fprintf(stderr, "No postfix string provided to send to server.\n");
return false;
}
printf("Sending postfix to server\n");
int err = send(client_socket_fd,
p_postfix,
strnlen(p_postfix, MAX_BUFFER_SIZE),
0);
if(strnlen(p_postfix, MAX_BUFFER_SIZE) > err)
{
fprintf(stderr,
"Unable to send message to server. [%s]\n",
strerror(errno));
return false;
}
char response[MAX_BUFFER_SIZE] = { 0 };
printf("Waiting for receive\n");
err = recv(client_socket_fd, &response, MAX_BUFFER_SIZE, 0);
if (0 == err)
{
fprintf(stderr,
"Connection to server lost. [%s]\n",
strerror(errno));
return false;
}
else if (0 > err)
{
fprintf(stderr,
"Unable to receive message on socket. [%s]\n",
strerror(errno));
return false;
}
printf("Server responded with: \n%s\n", response);
return true;
} /* send_postfix */
EDIT: https://github.com/TheStaplergun/Problem-Code
I uploaded the code to this repo and removed the need for the extraneous files I use and filled them with placeholders.
You can recreate this problem using the server with the command ./postfix_server -p 8888 -n 2 and the client issue in another terminal with for i in {1..4}; do ./postfix_client -i 127.0.0.1 -p 8888 -e "3 + $i" &> $i.txt & done
The output of each client will be forcefully flushed because of the setbuf at the top of client. Run it, see if any programs hang, if not run that command again. Just type PS and see if one of them is hanging, and look at the resulting text file. You will see it is stuck at the receive call.
If you sigint the server (CTRL + C), the client that was stuck will close with a Connection reset by peer response from the server, so the server still does have that file descriptor locked up somewhere.
I believe a race condition is happening somehow, because it only happens randomly.
A curious thing is it only happens ONCE PER SERVER INSTANCE.
If I kill that hung instance and proceed to do it again 10000 times it never does another hang until the server is reset.
For some reason, even with the following code flow inside of the
server, some clients "Fall through the cracks" and get stuck in limbo.
(They never get handled by the server so they just hang after
accepting the connection)
There may be other issues, but the first one I see is that main loop does not ensure that a new connection is actually picked up by any handler thread before it tries to hand off the next connection. Even if there are handler threads already blocked on the CV when a new connection is accepted, it is possible for the main server thread to signal the CV, loop back around, accept another connection, reacquire the mutex, and overwrite the new-connection FD before any handler thread picks up the previous one. The chances of that increase if you have more threads than cores.
Note that that will also interfere with your semaphore-based counting of available handlers -- you decrement the semaphore for every semaphore accepted, but you increment it again only for those that are successfully handled.
There are various ways that you could make the main server thread wait for the new connection to be picked up by a handler. One group would involve the server waiting on a CV itself, and relying on a handler to signal it after picking up the connection. Another, perhaps simpler, approach would involve using a semaphore to similar effect. But I would suggest instead not waiting, but instead creating a thread-safe queue for available connections, so that the server doesn't have to wait. That would even allow for queueing more connections than presently available handlers, if that would be useful to you.
I have the following code and I`m not sure why wont it work properly .
Its a multithreaded TCP server that loops accept() calls and triggers a designated
thread each time .
The problem is that the accept at times wont block , thus resulting
the program to open a new thread when there's theoretically no connection .
That's the loop -
for (dwI = 0;; dwI++) //Accept MAX_CLIENTS connections
{
if(MAX_CLIENTS == dwI)
{
dwI=0;
continue;
}//if
if(clients[dwI].bIsInUse)
{
continue;
}//if
ZeroMemory(&from,sizeof(from));
if(!AcceptConnection(&ServerSock,&from,&ClientSock))
{
PRINT_LE("AcceptConnection",ERROR_ACCEPT_SERVER_CONNECTION);
closesocket(ServerSock);
WSACleanup();
return EXIT_FAILURE;
}//if
clients[dwI].ClientSock = ClientSock;
if(! (clients[dwI].hThread = CreateThread(
NULL, //Not inheritable
0, //Default stack size
ThreadedAcceptTCP, //ThreadedAccept - function
&clients[dwI],//Pass pointer to the socket
0, //Start immidiately
&clients[dwI].dwThreadId //Save thread id
)))
{
PRINT_GLE("CreateThread");
closesocket(ServerSock);
WSACleanup();
return EXIT_FAILURE;
}//if
#ifdef PRINT_STATUS //Print status if macro is defined
printf("Server responce message has been sent.\n");
#endif
}//for
With my own wrappers to each function .
AcceptConnection has the code below -
SOCKET ClientSocket = INVALID_SOCKET; //Client socket
INT sockaddrSize = sizeof(*pSockAddr);
ClientSocket = accept( //Create client accepting socket
*pSock, //Listen-ed socket
pSockAddr,
&sockaddrSize
);
if (INVALID_SOCKET == ClientSocket) //Check for errors - if any - cleanup and return failure
{
PRINT_WSAGLE("socket");
return FAILURE;
}//if
*pClientSock = ClientSocket; //Pass socket
return SUCCESS;
The problem occurs when I connect to the server through my browser ,
for example ,
after the first thread is done (I`ve made this sure by temporarily sleeping the main thread for 5 seconds)
it cleans everything and closes the client socket ,
though on the second accept call - it will return with the same
SOCKADDR information and cause an extra thread to go up ,
receiving the exact same data , sending the exact same data .
And printing 2 (and at times even more) times :
"Server responce message has been sent."
I could'nt figure out why this happens and hopefully you guys could help me out .
Thanks !
This is a bit of a guess, but I wonder about the logic in this line of code:
if(!AcceptConnection(&ServerSock,&from,&ClientSock))
It is expecting AcceptConnection to return a non-zero value when it succeeds and a zero value when it fails. However, the function returns a constant SUCCESS when it succeeds. However, some of the Windows header files defined the constant SUCCESS to be 0. And various constants for failure are some non-zero value.
Even if you are defining SUCCESS and FAILURE in your own code, it might make sense to specifically check the return value such as:
if (FAILURE == AcceptConnection(&ServerSock,&from,&ClientSock))
One possible issue: it doesn't look like you are setting clients[dwI].bIsInUse to true after assigning a new client SOCKET, which will mess up your logic in your for loop.
I will start by saying that I am a college student with little c++ experience. How many times have you heard that right? I am working with the test program testISO_TCP (simplified version) from the libnodave library. This program does a simple read of flag values and data blocks while it is connected to a seimens 300 PLC. The program doesn't bring up any errors per se. What I am trying to do is hopefully add some code to this program that will protect the reads from ever crashing. Let me explain a little better. Say for example I have a lot of reads implemented in the code. As of now there are only two reads. Eventually I will run this code with many more reads. Now, say that I am running the test program and for some reason I lose the connection to the PLC. I would like to have the program do one of two things: 1) Once the connection is lost, do a retry connect a certain amount of times and when it runs out of tries, exit. or 2) Somehow continue to read from the PLC until they are all done.
I hope this is enough information to get some help. I will post the code that I have been looking at for so long without any idea how to do this effectively. Thanks to all in advance.
#define PLAY_WITH_KEEPALIVE
#include <stdlib.h>
#include <stdio.h>
#include "nodavesimple.h"
#include "openSocket.h"
#ifdef PLAY_WITH_KEEPALIVE
#include <winsock.h>
#endif
int main(int argc, char **argv) {
int a,b,c,res, doRun, doStop, doRead, doreadFlag, useProtocol, useSlot;
#ifdef PLAY_WITH_KEEPALIVE
int opt;
#endif
float d;
daveInterface * di;
daveConnection * dc;
_daveOSserialType fds;
doRun=0;
doStop=0;
doRead=0;
doreadFlag=0;
useProtocol=daveProtoISOTCP;
useSlot=2;
fds.rfd=openSocket(102, argv[1]);
#ifdef PLAY_WITH_KEEPALIVE
errno=0;
opt=1;
//res=setsockopt(fds.rfd, SOL_SOCKET, SO_KEEPALIVE, &opt, 4);
//LOG3("setsockopt %s %d\n", strerror(errno),res);
#endif
fds.wfd=fds.rfd;
if (fds.rfd>0)
{
di =daveNewInterface(fds,"IF1",0, daveProtoISOTCP, daveSpeed187k);
daveSetTimeout(di,5000000);
dc =daveNewConnection(di,2,0, 2); // insert your rack and slot here
if (0==daveConnectPLC(dc))
{
printf("Connected.\n");
res=daveReadBytes(dc,daveFlags,0,0,16,NULL);
if (0==res)
{
a=daveGetU32(dc);
b=daveGetU32(dc);
c=daveGetU32(dc);
d=daveGetFloat(dc);
printf("FD0: %d\n",a);
printf("FD4: %d\n",b);
printf("FD8: %d\n",c);
printf("FD12: %f\n",d);
}//end 0==res
}//end daveConnectPLC
else
{
printf("Couldn't connect to PLC.\n Please make sure you use the -2 option with a CP243 but not with CPs 343 or 443.\n");
//closeSocket(fds.rfd);
//return -2;
}
}//end fds.rfd
fds.rfd=openSocket(102, argv[1]);
fds.wfd=fds.rfd;
if (fds.rfd>0)
{
di =daveNewInterface(fds,"IF1",0, daveProtoISOTCP, daveSpeed187k);
daveSetTimeout(di,5000000);
dc =daveNewConnection(di,2,0, 2); // insert your rack and slot here
if (0==daveConnectPLC(dc))
{
printf("Connected.\n");
res=daveReadBytes(dc,daveDB,1,0,64,NULL);
if (0==res)
{
a=daveGetU16(dc);
printf("DB1:DW0: %d\n",a);
a=daveGetU16(dc);
printf("DB1:DW1: %d\n...\n",a);
a=daveGetU16At(dc,62);
printf("DB1:DW32: %d\n",a);
}//end 0==res
return 0;
}//end daveConnectPLC
else
{
printf("Couldn't connect to PLC.\n Please make sure you use the -2 option with a CP243 but not with CPs 343 or 443.\n");
closeSocket(fds.rfd);
return -2;
}
}//end fds.rfd
else
{
printf("Couldn't open TCP port. \nPlease make sure a CP is connected and the IP address is ok. \n");
return -1;
}
}// end main
You have to check the return value of the daveReadBytes function.
If it is not zero, something went wrong and you can use the daveStrerror function to get a proper error message:
printf ("error: %s\n", daveStrerror(res));
After that it's up to you to decide to either simply retry the read or disconnect (with closeSocket(...)) and then create a new connection from the beginning. Check the documentation on what errorcodes there are. Some errors can't be resolved by retrying (e.g. because you try reading a data block that doesn't exist).
I have a loop that attempts to connect 3 times and exits gracefully if it fails
You may be able to write some other code to first check to see if the connection is up and also if the PLC is up.
Typically if you try to connect to an IP address that doesn't esond; it will hang there and tie up resources...
I am also new programmer.But want to say that. First we have to differentiate between the TCP/IP connection with the ethernet card ISO_TCP. The openSocket() function does the connection to remote IP adress in the given port/Service (102 ISO_TCP). When called next, the function daveNewInterface(), it will initialise the specific interface for doing a connection to the PLC. After this, the function daveNewConnection() tries to open a connection on a given MPI adress, and very important, the given rack and slot. If this function returns the value 0, it will call the daveConnectPLC() function to connect to the PLC. At this point it´s established a ethernet connection,and also the PLC Connection.
Now you can use all the function from the libnodave library for read or write data, stop or run the PLC and much more.
In the actually simplified TCP_ISO code there are no function to disconnect the adapter or close the connection with the PLC, in your code there is the closeSocket() function and also the function that returns -2. Find at what line the code breaks, introducing for example a log after every function to see the returns values.
All info for detecting loss of communication is in the documentation.
Hi I have a problem with my function, which responsible for contact between client and server:
#define MAX 1024
void connection(int sock)
{
char buffer[MAX];
int newsock;
int n;
int r;
if(write(sock,"Hello!\n", 6) < 0)
{
perror("Error: ");
}
do {
if(write(sock, "\n> ",3) < 0)
{
perror(" Error: ");
}
memset(buffer,'0',MAX); // fill buffer
n = read(sock,buffer,MAX -1 );
if (strncmp("get",buffer,3) == 0)
{
execl("/usr/bin/top","/usr/bin/top","-n 1");
}
else if (strncmp("quit",buffer,4) == 0)
{
write(sock, "Exit from program\n",17);
close(sock);
}
else
{
write(sock,"Wrong order!\n", 12);
}
}
while(n);
}
When client send "get" the program should sends him view from "top" order, unfortunately it does not work in my program.
Secondly, please judge this code. This is my first server program. I will be very grateful
And finally, how to change function to give clients possibility to action in program after send "get" order.
Regards and Happy New Year!
You are calling exec without calling fork. So you are replacing your entire server process with a copy of top. This is really unlikely to do what you want.
Very likely, you could accomplish your aims by opening a suitable pseudo-file from the /proc file system, reading the information, and sending it into your socket.
If you really want to use top, you have to use pipe, fork and exec(l) to run top, read it's output from a pipe, and then send that output to the client.
It occurs to me that you might be running in an environment in which the server automatically forks you (like some sort of CGI gateway), in which case your problem is that you need to fdopen to move the socket to be descriptor #1 before exec-ing. It would really help if you would tell us all about your environment by editing your question.
The output of "top" goes to the server's stdout, not out through the socket to the client. You'd have to adjust the stdout of the "top" process for this to work.