LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Networking
User Name
Password
Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.

Notices


Reply
  Search this Thread
Old 07-06-2008, 05:29 PM   #1
lel4866
LQ Newbie
 
Registered: Jan 2005
Location: Raleigh, NC, USA
Distribution: Ubuntu 8.04
Posts: 5

Rep: Reputation: 0
real time signals work under gdb, not when run normally??


I'm messing around with the typical trivial web server app, written in c++ - but using c syntax, compiled with gcc, trying to use real time signals to tell when connections are made, etc.

I've written the thing using epoll, and it works fine.

In fact, as long as I run my app under gdb (with no breakpoints), it runs fine. However, if I just try to execute the app, it fails.

I test all the return codes for the calls to the socket libraries, and none are getting triggered. It fails as follows (I'm running Ubuntu desktop 8.04 on an Intel 8400 core 2 duo, Gigabyte motherboard, 4gb memory):

I start up and create the socket, do the bind and listen, create the signal set, and enter the wait loop with a call to sigwaitinfo. As soon as I use a browser to make a request on the port (localhost:8000),
Someone (not me) prints out the string:
Real-time signal 0, and the program terminates.

That's it. I never get a signal. Interestingly, when I run the app under gdb, It gets socket 4, but when I start the app directly, it gets socket 3. I guess gdb uses one.

Any suggestions?

Thanks.

Larry Lewis

Program follows:

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <sys/socket.h>
#include <sys/utsname.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/resource.h>
#include <bits/siginfo.h> // to set rlimit
#include <errno.h>
#include <sys/poll.h>

#define WAITING_FOR_REQUEST 1
#define socket_status(a) WAITING_FOR_REQUEST


int _GetHostName(char *buffer, int length);
int UseRealtimeSignals(int socket, long fileAccessMode = O_RDWR);

/*
*
*/
int main(int argc, char** argv) {
struct rlimit rlim;
int rc = getrlimit(RLIMIT_SIGPENDING, &rlim);
rlim.rlim_cur = 1024;
rc = setrlimit(RLIMIT_SIGPENDING, &rlim);
struct rlimit newrlim;
rc = getrlimit(RLIMIT_SIGPENDING, &newrlim);

// get WebServer1 Host information: NAME and INET ADDRESS
char hostname[256]; // large enough to hold this computer's host name
int status = _GetHostName(hostname, sizeof (hostname));
if (status != 0) {
perror("WebServer2:main.c:gethostname()");
return (EXIT_FAILURE);
}

struct hostent *hostPtr = gethostbyname(hostname);
if (hostPtr == NULL) {
perror("WebServer2:main.c:gethostbyname()");
return (EXIT_FAILURE);
}

int port = 8000;
struct sockaddr_in serverName;
memset(&serverName, 0, sizeof (serverName));
serverName.sin_addr.s_addr = htonl(INADDR_ANY);
serverName.sin_family = PF_INET;
serverName.sin_port = htons(port);
std::cout << "\nWebServer2 running at NAME: " << hostname << ". INET ADDRESS: " << inet_ntoa(serverName.sin_addr) << std::endl;

// Create socket on which to send and receive
int serverSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == 0) {
perror("WebServer1:main.c:socket()");
return (EXIT_FAILURE);
}
printf("serverSocket=%d\n", serverSocket);
if (UseRealtimeSignals(serverSocket, O_RDONLY) != 0)
return (EXIT_FAILURE);

// turn off bind address checking, and allow
// port numbers to be reused - otherwise
// the TIME_WAIT phenomenon will prevent
// binding to these address.port combinations
// for (2 * MSL) seconds.
int on = 1;
status = setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (const char *) & on, sizeof (on));
if (status != 0) {
perror("WebServer1:main.c:setsockopt(...,SO_REUSEADDR,...)");
close(serverSocket);
return (EXIT_FAILURE);
}

// bind socket to us
status = bind(serverSocket, (struct sockaddr *) & serverName, sizeof (serverName));
if (status != 0) {
perror("WebServer1:main.c:bind()");
close(serverSocket);
return (EXIT_FAILURE);
}

// accept TCP connections from clients
status = listen(serverSocket, 100); // allow 100 outstanding connections in the listen queue
if (status != 0) {
perror("WebServer1:main.c:listen()");
close(serverSocket);
return (EXIT_FAILURE);
}

// wait for real-time signals from any socket
sigset_t signalset;
siginfo_t siginfo;
int signum, sockfd, revents;

/* Wait only for RealTime signal SIGRTMIN. */
int rc1 = sigemptyset(&signalset);
int rc2 = sigaddset(&signalset, SIGRTMIN);
printf("sigemptyset=%d sigaddset=%d\n", rc1, rc2);

/* Check for socket events */
struct sockaddr_in clientName;
int clientSocket;
socklen_t clientLength = sizeof (clientName);
printf("starting event loop\n");
while (1) {
signum = sigwaitinfo(&signalset, &siginfo);
printf("got signal\n");

... irrelevant - never gets here


/*
* Local replacement of gethostname() to aid portability
*/
int _GetHostName(char *buffer, int length) {
struct utsname sysname;
int status = uname(&sysname);
if (status == 0) {

strncpy(buffer, sysname.nodename, length);
}
return (status);
}

// Set socket to use real time signal
// file AccessMode can be O_RDONLY, O_WRONLY, O_RDWR

int UseRealtimeSignals(int socket, long fileAccessMode) {
int rc;

// Set socket flags to non-blocking and asynchronous */
if ((rc = fcntl(socket, F_SETFL, fileAccessMode | O_NONBLOCK | O_ASYNC)) != 0) {
perror("WebServer2:main.c:UseRealtimeSignals()");
return rc;
}

// Set signal number >= SIGRTMIN to send a RealTime signal */
if ((rc = fcntl(socket, F_SETSIG, SIGRTMIN)) != 0) {
perror("WebServer2:main.c:UseRealtimeSignals()");
return rc;
}

// Set process id to send signal to */
if ((rc = fcntl(socket, F_SETOWN, getpid())) != 0) {
perror("WebServer2:main.c:UseRealtimeSignals()");
return rc;
}

return 0;
}
 
Old 07-06-2008, 06:15 PM   #2
Mr. C.
Senior Member
 
Registered: Jun 2008
Posts: 2,529

Rep: Reputation: 63
Running under GBD, GDB likely blocks the signal by default.

Any relevance? :

http://www.linuxquestions.org/questi...nation-474278/
 
Old 07-06-2008, 09:30 PM   #3
lel4866
LQ Newbie
 
Registered: Jan 2005
Location: Raleigh, NC, USA
Distribution: Ubuntu 8.04
Posts: 5

Original Poster
Rep: Reputation: 0
Thanks for the suggestion.

Unfortunately, A further note on investigation:

I changed the signal number to SIGRTMIN+3, and now it dies with
Real time signal 3
instead of 0.

So, it apparently doesn't think I'm handling the actual signal I'm trying to handle. So the theory that gdb is blocking it is probably not correct.
 
Old 07-06-2008, 09:50 PM   #4
Mr. C.
Senior Member
 
Registered: Jun 2008
Posts: 2,529

Rep: Reputation: 63
The signal number change makes sense; there are at least a minimum of 7 real time signals by POSIX standard. The error messages comes from libc:

$ strings /lib/libc.so.6 | grep Real
Real-time signal %d

You can see how %d changes with signal number, an offset from SIGRTMIN. Run your app under strace, and see where it dies.

When the app dies because of a signal, you can rest assured that the signal is not being caught. Perhaps some clues exist in how you are compiling or linking (the libraries for example).

Last edited by Mr. C.; 07-06-2008 at 09:53 PM.
 
Old 07-06-2008, 11:27 PM   #5
skoona
Member
 
Registered: Mar 2004
Location: Indiana, USA
Distribution: Fedora, CentOS, Ubuntu, OS/X, Raspbian
Posts: 90

Rep: Reputation: 18
Reviewed you code, it would help if I had all of it and the g++ compile statement or makefile.

Using realtime signals instead of listen/accept() is interesting, but since you have started down this path here are a few quick observations.

SIGRTMIN is part of a range bounded by SIGRTMAX. Posix suggest that its at least 8 entrys wide. based on $man 7 signal (Real-time Signals section) I would expect SIGRTMIN to equal 33-35, and not 0. No matter what the actual value is your sigXXXset() is very narrow or only 1 value wide: open it up for testing. Actually, based on all the users of real-time signals I would start by using SIGRTMAX rather than SIGRTMIN. Note: Fedora 8 start SIGRTMIN at 32.

1. Open/widen sigwaitinfo()
sigemptyset(&sig_real)
sigaddset(&sig_real, SIGRTMAX)
sigaddset(&sig_real, SIGRTMAX-1)
sigaddset(&sig_real, SIGRTMAX-2)
sigaddset(&sig_real, SIGRTMAX-3)

Now sigwaitinfo() is wide enough for you to catch the real number before libc terminates the program. (uncaught SIGRTxxx signals have a default action of terminate)

2. Use SIGRTMAX-1 instead of SIGRTMIN everywhere. Serveral things (like pthreads) use some of the lower rt signals, so starting from the other end ensures your in the clear.


3. Setting up signals on normal socket operations early, might be getting triggered by the sockopts/bind/listen() calls themselves. Set a signal Block on the SIGRTMAX-range of early so they can't fire until you issue a sigwaitinfo() later. consider using 'pthread_sigmask(SIG_BLOCK, &sig_real, NULL)' right after your get/setrlimit() calls (which you are not checking return codes on).

Comments:
A. Here is some C/GLIB based utils that might give you a few alternate ideals. http://mysite.verizon.net/skoona/sit...-0.1.9.tar.bz2

Last edited by skoona; 07-06-2008 at 11:45 PM. Reason: Changed observation 3, and added a comment.a
 
Old 07-06-2008, 11:40 PM   #6
Mr. C.
Senior Member
 
Registered: Jun 2008
Posts: 2,529

Rep: Reputation: 63
Nice Skoona. I knew you'd be more up to date than I am; I've gotten rusty. Thanks for the follow-up.
 
Old 07-06-2008, 11:40 PM   #7
pinniped
Senior Member
 
Registered: May 2008
Location: planet earth
Distribution: Debian
Posts: 1,732

Rep: Reputation: 50
I don't see your call to sigprocmask(), so as far as the system is concerned signals will be delivered in the normal way, which usually results in the process being killed because you didn't handle the signal.

You need to 'block' all the signals which you plan to use with sigwaitinfo().
 
Old 07-06-2008, 11:57 PM   #8
Mr. C.
Senior Member
 
Registered: Jun 2008
Posts: 2,529

Rep: Reputation: 63
Right!:

man sigwaitinfo()

...

Behaviour of these functions is unspecified if any of the signals in set
are unblocked at the time these functions are called.
 
Old 07-07-2008, 12:09 AM   #9
skoona
Member
 
Registered: Mar 2004
Location: Indiana, USA
Distribution: Fedora, CentOS, Ubuntu, OS/X, Raspbian
Posts: 90

Rep: Reputation: 18
The keys are "block the signals you plan to use" from pinniped; and "Behaviour of these functions is unspecified if any of the signals in set are unblocked at the time these functions are called." from Mr. C.

Let await the results - I think we found it. oh - pthread_sigmask and sigprocmask are multi-thread and single-threaded peers.

James,
 
Old 07-07-2008, 11:31 AM   #10
lel4866
LQ Newbie
 
Registered: Jan 2005
Location: Raleigh, NC, USA
Distribution: Ubuntu 8.04
Posts: 5

Original Poster
Rep: Reputation: 0
Added the sigprocmask and it works!

You guys are amazing - thanks very much.

I'm just a recent convert to linux programming - been a Windows programmer for 20 years until 3 months ago. I really didn't expect such a quick and thourough response.

I wanted to try writing a very efficient web server (for fun - not a commercial effort), and after reading about select and epoll, I wondered, why not just bypass everyone else's attempts and buffering and queueing and implement my own stuff to see what's really happeneing. That's why I wanted to get real-time signals to work (I believe the kernel still does some buffering). But, I can't really seem to find much information on the difference between real-time signals and normal signals. Are they really more efficient or higher priority?

Thanks again.

Larry Lewis
 
Old 07-07-2008, 01:31 PM   #11
Mr. C.
Senior Member
 
Registered: Jun 2008
Posts: 2,529

Rep: Reputation: 63
See: http://www.embedded.com/story/OEG20010312S0073
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
LXer: Real-time Linux gains real-time JVM LXer Syndicated Linux News 0 10-12-2006 10:54 AM
Real Time Signals getting EPERM warrenpatrick Programming 4 08-25-2006 09:29 AM
real-time signals cause program termination miles_christian Programming 2 08-21-2006 10:59 PM
how can I measure how much real time is used to run an executable? markhod Linux - General 1 04-07-2005 04:41 AM
run real time echox Programming 3 04-03-2003 02:01 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Networking

All times are GMT -5. The time now is 02:57 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration