| Oracle FAQ | Your Portal to the Oracle Knowledge Grid | |
Home -> Community -> Usenet -> c.d.o.misc -> Re: Unix signal handling using PRO*C
jedimaster (jedimast_at_concentric.net) wrote:
: Can anyone give me some example code showing the proper way to handle : SIGINT and SIGCHLD signals in a Unix program? I'm having a problem : with core dumps occuring under 7.3.3 when I try to trap these two : signals?
: Thanks,
: Bob
: =====================================================: "When the long night comes, return to the end of the beginning."
: Message from Ambassador Kosh to Sheridan - Babylon 5
: =====================================================
It's a part of code of my unix daemon with signal handlers and comments. This works fine under Digital Unix. Enjoy!
/* * sq network daemon * sq - designed for System V and BSD compatibility * Created by Alexey Reshetov, 16.12.96. * References to network server from R.Stevens. */#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include <syslog.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
/* #include "sqlca.h" */
EXEC SQL INCLUDE sqlca;
int Port; /* Port number for communications */
typedef char asciiz[40];
EXEC SQL TYPE asciiz IS STRING(40) REFERENCE;
asciiz username; asciiz password; asciiz col_name;
char table_name[40];
char oracle_sid[40];
char oracle_home[40];
void sql_error(); /* For ORACLE exceptions and LOGIN Errors */
void reapchild();
void die();
void init();
void onalarm();
void gettimenow();
int stat_file();
char *pname;
char str[2] = "#"; /* Null value for control table */
int start_flg; /* At start flag == 0, at restrart flag = 1, then 0 */
#define PID_FILE "/var/run/sq.pid"
#define CONF_FILE "/var/adm/sq/sq.conf"
#define LOG_FILE "/var/adm/sq/sq.log"
#define MAXLINE 80
int TIMERINT = 1; /* default time value for TIMER */
pid_t childpid; /* childpid - clobal variable, therefore easy * to kill child, but if at one time there are * few childs (i.e. few connections), then * childpid will redefined, and it will difficult * way to kill correctly. */
main( int argc, char *argv[])
{
int sockfd, newsockfd, clilen, fd;
struct sockaddr_in serv_addr, cli_addr;
struct servent *sp;
int status;
pid_t pid;
FILE *fp;
static struct stat statbuf;
char buf[MAXLINE];
char hostname[MAXHOSTNAMELEN]; /* local host name */
start_flg = 0;
/* unlink(LOG_FILE); */
pname = argv [0];
if ((sp = getservbyname("sq", "tcp")) == NULL)
{
fprintf(stderr, "sq/tcp: unknown service\n");
err_dump("sq/tcp: unknown service");
exit (-1);
}
/* User's default parameters for connect to ORACLE */
strcpy(username, "Frank");
strcpy(password, "Zappa");
EXEC SQL WHENEVER SQLERROR DO sql_error("ORACLE ERROR--");
EXEC SQL WHENEVER NOT FOUND DO break;
/*
* If we are not started in the background ( there should be
* important _if_ above), fork and let parent exit.
* This also guarantees the first child is not a process
* group leader
*/
if ( (childpid = fork()) < 0 )
err_dump("can't fork first child");
else if ( childpid > 0)
exit(0); /* parent */
/*
* First child process
*/
if (stat_file (CONF_FILE, R_OK) != 0)
{
fprintf(stderr, "sq: Can't stat config file.\n");
exit (-1);
}
init (0);
if (stat(PID_FILE, &statbuf) == 0)
{
fprintf(stderr, "File %s exists!\n", PID_FILE);
exit (-1);
}
else if ((fp = fopen (PID_FILE, "w")) != NULL)
{
fprintf(fp, "%d\n", getpid());
(void) fclose (fp);
}
else if (fp == NULL)
{
fprintf(stderr, "Can't open file %s\n", PID_FILE);
exit (-1);
}
/* Set environment variables */
if (setenv("ORACLE_HOME", oracle_home, 1) != 0)
{
fprintf(stderr, "ORACLE_HOME is not set\n");
err_dump("ORACLE_HOME is not set");
exit (-1);
}
if (setenv("ORACLE_SID", oracle_sid, 1) != 0)
{
fprintf(stderr, "ORACLE_SID is not set\n");
err_dump("ORACLE_SID is not set");
exit (-1);
}
/*
* Disassociate from Contol Terminal and process group.
* Ensure the process can't reaquire a new contorlling terminal.
*/
/* For BSD, not for System V
if ( setpgrp(0, setpid()) == -1 )
err_dump("can't change process group");
*/
if ( (fd = open("/dev/tty", O_RDWR )) >= 0)
{
ioctl(fd, TIOCNOTTY, (char *)NULL); /* lose controlling tty */
close(fd);
};
/*
* Close any open files ( stdin, stdout etc ) descriptors
*/
for (fd =0; fd < NOFILE; fd++ )
close(fd);
/*
* Move current directory to root
*/
chdir("/");
/*
* Set file mode creation mask.
*/
umask(022);
/* SIGNALS */
(void) signal (SIGHUP, init);
(void) signal (SIGTERM, die);
(void) signal (SIGINT, die);
(void) signal (SIGQUIT, die);
/*
* Don't wait child signals. This successfully prevent
* ugly zombies creation
*/
(void) signal ( SIGCHLD, reapchild );
/*
* Open a TCP socket ( an Internet stream socket )
*/
if ( (sockfd = socket (AF_INET, SOCK_STREAM, 0 )) <0)
err_dump("can't open stream socket");
/*
* Bind our local address so that the client can send to us
*/
bzero( (char *) &serv_addr, sizeof(serv_addr) );
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = Port = sp->s_port;
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
err_dump("can't bind local address");
exit (-1);
}
pid = getpid();
listen( sockfd, 5 );
for(;;)
{
/*
* Wait for a connection from client process
* This is an example of concurrent server
*/
clilen = sizeof(cli_addr);
newsockfd=accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if ( newsockfd < 0 )
{
if (start_flg == 0)
err_dump("accept error");
}
signal (SIGALRM, onalarm);
alarm(TIMERINT);
if ((childpid = fork()) < 0)
err_dump("fork error");
else if (childpid == 0 )
{ /* child process */
close(sockfd); /* close original socket */
EXEC SQL CONNECT :username IDENTIFIED BY :password;
EXEC SQL DECLARE linkstat CURSOR FOR
SELECT req_atr FROM control_ip_connect;
EXEC SQL OPEN linkstat;
EXEC SQL FETCH linkstat INTO :str;
EXEC SQL CLOSE linkstat;
EXEC SQL COMMIT WORK RELEASE;
str_echo(newsockfd, str); /* process the request */
close(newsockfd);
exit(getpid());
}
else if (childpid > 0)
{
while (waitpid(childpid, &status, 0) != 0)
break;
signal (SIGALRM, SIG_IGN);
/* If the wait, waitpid, wait3, or wait4 function returns
* because the status of a child process is available, the
* process ID of the child is returned to the calling process.
* If they return because a signal was caught by the calling
* process, -1 is returned and errno is set to [EINTR].
* If the WNOHANG option was specified, and there are no
* stopped or exited child processes, the waitpid, wait3,
* and wait4 functions return a value of zero (0). Otherwise,
* -1 is returned and errno is set to indicate the error.
*/
}
close(newsockfd); /* in parent process */
start_flg = 0;
sleep(TIMERINT+1);
}
exit (0);
/* init - read config file
* config file allows comments (#)
*/
/*
* die - to kill all child processes, close all opened files
/* Close all opened files */
for (fd = 0; fd < NOFILE; fd++)
close (fd);
if (signo != 0)
{
sprintf(buf, "die: Process %d Exiting on signal %d",
getpid(), signo);
err_dump(buf);
errno = 0;
}
/*
if (unlink(PID_FILE) != 0)
err_dump("die: Can't delete pid-file");
*/
exit (0);
void sql_error(msg)
char *msg;
{
char err_msg[512]; char buf[1024]; size_t buf_len, msg_len; EXEC SQL WHENEVER SQLERROR CONTINUE; sprintf(buf, "SQL-%s\n", msg); err_dump(buf); /* Call sqlglm() to get the complete text of the error message. */ buf_len = sizeof (err_msg); sqlglm (err_msg, &buf_len, &msg_len); sprintf(buf, "SQL-%s.%s\n", msg_len, err_msg); err_dump(buf); EXEC SQL ROLLBACK RELEASE; return;
/* * reapchild() */
void reapchild (int signo)
{
/*
* Use the wait3() systems call with the WNOHANG option
*
*/
/* union wait status; */
int status;
while (wait3( (int *)&status, WNOHANG, (struct rusage *) NULL) > 0)
;
/* * onalarm - after received signal SIGALRM, kill child process */
void onalarm(int signo)
{
char buf[80];
sprintf(buf, "onalarm - kill child process %d", childpid); err_dump(buf); kill (childpid, SIGINT);
![]() |
![]() |