mod_fcgid windows named pipes 2nd and subsequent requests - c

All, I'm building a fastCGI interface for a programming language which is run-time based, and runs in Windows, Linux and UNIX environments.
I've implemented the fastCGI protocol within program code that runs within that run-time but I'm having an issue with Windows code which talks to mod_fcgid. In this case I cannot use prebuilt dll's to expose fastCGI functions, but I can make calls to most C functions from within that runtime language. I cannot modify the runtime as it belongs to another company... Think of it as being a php or perl like language. What I'm trying to do is similar to creating a dll like set of code (its not a dll) to process a fastCGI request. While many would say I'm "re-inventing the wheel" here, I have no choice of using someone's prebuilt dll to provide the interface to fastCGI.
I've successfully implemented everything and I can get the initial request, and respond back with a web page thru my fastCGI interface. The problem I am having is dealing with the "next" request when running under Windows. My code when running under Linux works terrific, I accept() the socket, read() write() to do my processing, close() the socket, and then go back and accept() again, and I get the next request and everything processes perfectly.
Under Windows mod_fcgid uses named pipes. Within my code I use GetStdHandle() to get a handle to stdin, then use ReadFile() and WriteFile() and the data wrapped in the fastCGI protocol goes to mod_fcgid and then on to the browser when done with a request I use CloseHandle() and then am looping back to GetStdHandle() to wait for the next request.
Everything works perfectly for the first request, the browser gets my cgi output. The same code under Linux using sockets, gets the 2nd and subsequent requests and works like a charm.
My issues is: when running under Windows, after I process the first request, I cannot get mod_fcgid to send me a second request. It will end up killing my windows process and starts a new one in its place. Which of course is not what I want.
I must being doing something wrong between the time I send the fastCGI EndRequest and when I loop around to wait for the next request to come in.
To get the initial request from mod_fcgid, I use GetStdHandle() then I use ReadFile() and WriteFile() (all from kernel32.dll) and when I've finished the protocol with its EndRequest, I cannot get the code right to be able to receive a second request.
I've tried fflush() I've tried FileFlushBuffers(), I've tried not closing the handle I was given from GetStdHandle(), I simply cannot figure out what mod_fcgid needs from my windows app so that I can receive the second and subsequent requests.
After the first request, closing my handle, getting a handle to stdin from GetStdHandle, and then sitting on ReadFile, The ReadFile() comes back with 0 bytes, and GetLastError() always returns 6 (Invalid Handle).
I simply cannot figure out the C functions to use to cleanup after the first request is complete and to be able to wait for the next request to come in when running under Windows. As I've said before the code works perfect under Linux when using sockets instead of Windows which is using a handle from STDIN that is a named pipe.

Harry, your comment on using the NamedPipe functions did the trick, I needed to use FileFlushBuffers followed by a DisconnectNamedPipe at the end of the first request, and then a ConnectNamedPipe to wait for the next request to come in. Thank you again.

Related

Programmatically detect if local web server has hung

I realise that I'll get at least one answer along the lines of "(re)write the code so it doesn't hang" but let's assume we don't live in that shiny happy utopia just yet...
In our embedded system we have a big SDK including a web-server (Boa) which is the primary method of user interaction.
It's possible, during certain phases of the moon, that something can cause the web server to hang or become otherwise stuck in such a way that the process appears running normally (not crashed/dead/using 100% CPU) but does not serve any web pages.
So, the question is, how do we test/detect this situation?
To test whether the server is hung, create a TCP socket and connect to port 80 on IP address 127.0.0.1 (loopback address). Then send the following text over the socket
GET / HTTP/1.1\r\n\r\n
Most servers will interpret that as a request for index.html. Alternatively, you could implement an undocumented URL for testing (which allows for a shorter, predetermined response), e.g.
GET /test/fdoaoqfaf12491r2h1rfda HTTP/1.1\r\n\r\n
You then need to read the response from the server. This involves using select with a reasonable timeout to determine whether any data came back from the server, and if so, use recv to read the data. The response from the server will consist of a header followed by content. The header consists of lines of text, with a blank line at the end of the header. Lines end with \r\n, so the end of the header is \r\n\r\n.
Getting the content involves calling select and recv until recv returns 0. This assumes that the server will send the response and then close the socket. Some sophisticated servers will leave a socket open to allow multiple requests over the same socket. A simple embedded server should not be doing that. (If your server is trying to use the same socket for multiple requests, then you need to figure out how to turn that feature off.)
That's all very well and good, but you really need to rewrite your code so it doesn't hang.
The mostly likely cause of the problem is that the server has a bunch of dangling sockets, i.e. connections from clients that were never properly cleaned up. Dangling sockets will eventually prevent the server from accepting more connections, either because the server has a limit on the number of open connections, or because the process that's running the server uses up all of its file descriptors.
The first thing to check is the TCP timeout value. One project that I worked on had a default timeout of 5 hours, which meant that dangling sockets stayed open for 5 hours. A reasonable timeout is 1 minute.
Then you need to create a client that deliberately misbehaves. Clients can misbehave by
leaving a socket open without reading the server's response
abruptly closing the socket while reading the response
gracefully closing the socket while reading the response
The first situation should be handled by the TCP timeout. The other two need to be properly handled by the server code. Graceful and abrupt socket closure is controlled via the SO_LINGER option of ioctl and the shutdown function. After the client misbehaves, check the number of open file descriptors in the server process, to verify that the server has handled the situation correctly.

In C on Linux, how would I go about using 2 programs, the latter sending text data to the first displayed using stdout?

I am writing a simple instant messenger program in C on Linux.
Right now I have a program that binds a socket to a port on the local machine, and listens for text data being sent by another program that connected to my local machine IP and port.
Well, I can have this client send text data to my program, and have it displayed using stdout on my local machine; however, I cannot program a way to send data back to the client machine, because my program is busy listening and displaying the text sent by the client machine.
How would I go about either creating a new process (that listens and displays the text sent to it by the client machine, then takes that text and sends it to the other program's stdout, while the other program takes care of stdin being sent to the client machine) or create 2 programs that do the separate jobs (sending, receiving, and displaying), and sends the appropriate data to one another?
Sorry if that is weirdly worded, and I will clarify if need be. I looked into exec, execve, fork, etc. but am confused as to whether this is the appropriate path to look in to, or if there is a simpler way that I am missing.
Any help would be greatly appreciated, Thank you.
EDIT: In retrospect, I figured that this would be much easier accomplished with 2 separate programs. One, the IM server, and the others, the IM clients.
The IM Clients would connect to the IM server program, and send whatever text they wanted to the IM server. Then, the IM server would just record the data sent to it in a buffer/file with the names/ip's of the clients appended to the text sent to it by each client, and send that text (in format of name:text) to each client that is connected.
This would remove the need for complicated inter-process/program communication for stdin and stdout, and instead, use a simple client/server way of communicating, with the client programs displaying text sent to it from server via stdout, and using stdin to send whatever text to the server.
With this said, I am still interested in someone answering my original question: for science. Thank you all for reading, and hopefully someone will benefit from my mental brainstorming, or whatever answers come from the community.
however, i cannot program a way to send data back to the client machine, because my program is busy listening and displaying the text sent by the client machine.
The same socket that was returned from a listening-socket by accept() can be used for both sending and receiving data. So your socket is never "busy" just because you're reading from it ... you can write back on the same socket.
If you need to both read and write concurrently, then share the socket returned from accept() across two different threads. Since two different buffers are being used by the networking stack for sending and receiving on the socket, a dedicated thread for reading and another dedicated thread for writing to the socket will be thread-safe without the use of mutexes.
I would go with fork() - create a child process and now you have two different processes that can do two different things on two different sockets- one can receive and the other can send. I have no personal experience with coding a client/server like this yet, but that would be my first stab at solving your issue...
As #bdonlan mentioned in a comment, you definitely need a multiplexing call like select or preferably poll (or related syscalls like pselect, ppoll ...). These multiplexing calls are the primitive to wait on several channels at once (with pselect and ppoll able to atomically wait for both I/O events and signals). Read also the select tutorial man page. Of course, you can wait for several file descriptors, and you can wait for both reading & writing abilities (even on the same socket, if needed), in the same select or poll syscall.
All event-based loops and frameworks are using these multiplexing calls (like poll or select). You could also use libevent, or even (particularly when coding a graphical user interface application) some GUI toolkit like Gtk or Qt, which are all based around a central event loop.
I don't think that having a multi-process or multi-threaded application is useful in your case. You just need some event loop.
You might also ask to get a SIGIO signal when data arrives on your socket using fcntl with F_SETOWN, but this is not very useful for you. Then you often want to have your socket non-blocking.

Going from listen and fork to xinetd

I have a piece of C network software that currently works in listen and fork mode. It's listening on some server socket and accepts incoming connection. Then it calls the core server function providing the new accepted socket.
Now I'm trying to make that software also work behind xinetd (depending on some runtime parameter). I tried to directly call the core server function providing file descriptor 0 instead of an accepted socket, but this method is just not working. The program immediately stops with a SIG_PIPE.
Is there any obvious reason for such behavior ? My core function performs some low level socket calls and signal handling. Is that supposed to work behind xinetd ?
Not absolutely certain but not everything you can do on a socket handle also works with ordinary file handles. For a start, you can't write to stdin. Also some system calls probably need a socket e.g. recv().
Edit
Another possibility: does your server process close stdin as part of its start up?

windows C program perform action on shutdown

I am making a program that sends "heartbeats" for a server to keep track of nodes. They are packets with the following payloads:
'start' when it starts up
'running' every 5 seconds
'stopping' at shutdown
The first two are easy. The thread/loop can set the message on first and subsequent runs. How do I make the loop "catch" a shutdown so that it can send a last packet?
I use the minGW compiler for C in WinXP platform.
Edit: I added the relevant details I missed (thanks walkingTarget and Ferruccio)
It is an in-progress app that contains messy stuff in implementation :-)
It uses libCURL, the HTTP client library to send the packets
It is a console app, which I (much later) intend as a service
It needs to save a file and send a packet at shutdown
It needs to capture a system shutdown
In your WindowProc() you can check for the message WM_QueryEndSession, which Windows sends to all open processes before shutting down. For more info on that message see the following link, but i understand that it is as trivial as checking for a WM_SIZE:
http://msdn.microsoft.com/en-us/library/aa376890%28VS.85%29.aspx

How to find where a process is stuck using DDD

I have a TCP Svr process written in C and running on CentOS 5.5. It acts as a TCP Server for external clients and also does some IPC communication with other processes in the system using Unix Domain Sockets it has establised. It's not a multi threaded process. It does one task at a time. There's an epoll_wait() I use to listen for requests on either the TCP socket or any of the IPC sockets it has established with internal processes. When the epoll_wait() function breaks,I process the request for whoever it is and then go back into epoll_wait()
I have a TCP Client that connects to this Process from outside (not IPC). It connects sucessfully, sends a request msg, gets a response back. I've put this in an infinite loop
just to test out its robustness etc.
After a while, the TCP Server stops responding to requests coming from TCP Client. The TCP client connects successfully, sends a request message, but it doesnt get any response msg back from the TCP server.
So I reckon the TCP server is stuck somewhere else, trying to do something and has not returned to the epoll_wait() to process
other requests coming in. I've tried to figure it out using logs, but thats not helping me understand where exactly the process is stuck.
So I wanted to use any debugger that can give me some information (function name would be great), as to what the process is doing. Putting breakpoints, is overwhelming cause the TCP Server process has tons of files and functions....
I'm trying to use DDD on CentOS 5.5, to figureout whats going on. I attach to the process successfully. Then I click on "Step" or "Stepi" or "Next" button....
but nothing happens....
btw when I use Eclipse for debugging, and attach to this process (or any process), I always get "__kernel_vsyscall()"....Does this mean, the program breaks by default at
whatever its doing? If thats the case, how do I come out of the __kernel_vsyscall() call, to continue within my program? If I press f8, it comes out, but then I dont know where it was, since I loose the stack trace....Like I said earlier. Since I cant figure where it was, I dont know where to put breakpoint....
In summary, I want to figureout where my process is stuck or what its doing and try to debug from that point on....
How do I go about this?
Thanks
Amit
1) Attaching to a C process can often cause problems in itself, is there any way for you to start the process in the debugger?
2) Using the step functions of DDD need to be done after you've set a breakpoint and the program is stopped on a command. From reading your question, I'm not sure you've done that. You may not want to set many breakpoints, but is setting one or two in critical sections of code possible?
In summary, What I wanted to accomplish was to be able to find where my program is stuck, when it hangs. I figured it out - It was so simple. Create a configuration in Eclipse ...."Debug Configurations->C/C++ attach to application"...
Let the process run normally from shell (preferably with a terminal attached). When it hangs, open eclipse, click on the debug icon and run the configured process. It'll ask you to attach to a process. Look for your process name and attach to it.
Now, just look at the entire stack trace....you'll see some of your own function calls mixed with kernel function calls. That tells you where the program is stuck.

Resources