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);
![]() |
![]() |