/*
- * Copyright (c) 1995-2004, Index Data
+ * Copyright (C) 1995-2005, Index Data ApS
* See the file LICENSE for details.
*
* NT threaded server code by
* Chas Woodfield, Fretwell Downing Informatics.
*
- * $Id: statserv.c,v 1.12 2004-11-18 15:18:13 heikki Exp $
+ * $Id: statserv.c,v 1.19 2005-01-16 21:51:50 adam Exp $
*/
/**
#include <winsock.h>
#include <direct.h>
#include "service.h"
-#else
+#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#if HAVE_UNISTD_H
#include <unistd.h>
+#endif
+#if HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef USE_XTIMOSI
#include <yaz/xmosi.h>
#endif
-#include <yaz/ylog.h>
+#include <yaz/log.h>
#include "eventl.h"
#include "session.h"
#include <yaz/statserv.h>
static int max_sessions = 0;
-static int logbits_set=0;
-static int log_session=0;
-static int log_server=0;
+static int logbits_set = 0;
+static int log_session = 0;
+static int log_server = 0;
/** get_logbits sets global loglevel bits */
static void get_logbits(int force)
{ /* needs to be called after parsing cmd-line args that can set loglevels!*/
if (force || !logbits_set)
{
- logbits_set=1;
- log_session=yaz_log_module_level("session");
- log_server=yaz_log_module_level("server");
+ logbits_set = 1;
+ log_session = yaz_log_module_level("session");
+ log_server = yaz_log_module_level("server");
}
}
static void listener(IOCHAN h, int event)
{
COMSTACK line = (COMSTACK) iochan_getdata(h);
- static int hand[2];
- static int child = 0;
int res;
if (event == EVENT_INPUT)
{
- if (control_block.dynamic && !child)
+ COMSTACK new_line;
+ if ((res = cs_listen_check(line, 0, 0, control_block.check_ip,
+ control_block.daemon_name)) < 0)
+ {
+ yaz_log(YLOG_WARN|YLOG_ERRNO, "cs_listen failed");
+ return;
+ }
+ else if (res == 1)
+ {
+ yaz_log(YLOG_WARN, "cs_listen incomplete");
+ return;
+ }
+ new_line = cs_accept(line);
+ if (!new_line)
+ {
+ yaz_log(YLOG_FATAL, "Accept failed.");
+ iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */
+ return;
+ }
+ no_sessions++;
+ if (control_block.dynamic)
{
- int res;
-
- ++no_sessions;
- if (pipe(hand) < 0)
- {
- yaz_log(YLOG_FATAL|YLOG_ERRNO, "pipe");
- iochan_destroy(h);
- return;
- }
if ((res = fork()) < 0)
{
yaz_log(YLOG_FATAL|YLOG_ERRNO, "fork");
char nbuf[100];
IOCHAN pp;
- close(hand[0]);
- child = 1;
for (pp = pListener; pp; pp = iochan_getnext(pp))
{
- if (pp != h)
- {
- COMSTACK l = (COMSTACK)iochan_getdata(pp);
- cs_close(l);
- iochan_destroy(pp);
- }
+ COMSTACK l = (COMSTACK)iochan_getdata(pp);
+ cs_close(l);
+ iochan_destroy(pp);
}
sprintf(nbuf, "%s(%d)", me, no_sessions);
yaz_log_init(control_block.loglevel, nbuf, 0);
}
else /* parent */
{
- close(hand[1]);
- /* wait for child to take the call */
- for (;;)
- {
- char dummy[1];
- int res;
-
- if ((res = read(hand[0], dummy, 1)) < 0 &&
- yaz_errno() != EINTR)
- {
- yaz_log(YLOG_FATAL|YLOG_ERRNO, "handshake read");
- return;
- }
- else if (res >= 0)
- break;
- }
- yaz_log(YLOG_DEBUG, "P: Child has taken the call");
- close(hand[0]);
+ cs_close(new_line);
return;
}
}
- if ((res = cs_listen_check(line, 0, 0, control_block.check_ip,
- control_block.daemon_name)) < 0)
- {
- yaz_log(YLOG_WARN|YLOG_ERRNO, "cs_listen failed");
- return;
- }
- else if (res == 1)
- return;
- yaz_log(YLOG_DEBUG, "listen ok");
- iochan_setevent(h, EVENT_OUTPUT);
- iochan_setflags(h, EVENT_OUTPUT | EVENT_EXCEPT); /* set up for acpt */
- }
- /* in dynamic mode, only the child ever comes down here */
- else if (event == EVENT_OUTPUT)
- {
- COMSTACK new_line = cs_accept(line);
-
- if (!new_line)
- {
- yaz_log(YLOG_FATAL, "Accept failed.");
- iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */
- return;
- }
- yaz_log(YLOG_DEBUG, "accept ok");
- if (control_block.dynamic)
- {
- IOCHAN pp;
- /* close our half of the listener socket */
- for (pp = pListener; pp; pp = iochan_getnext(pp))
- {
- COMSTACK l = (COMSTACK)iochan_getdata(pp);
- cs_close(l);
- iochan_destroy(pp);
- }
- /* release dad */
- yaz_log(YLOG_DEBUG, "Releasing parent");
- close(hand[1]);
- }
- else
- {
- iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */
- ++no_sessions;
- }
-#if YAZ_POSIX_THREADS
if (control_block.threads)
{
+#if YAZ_POSIX_THREADS
pthread_t child_thread;
pthread_create (&child_thread, 0, new_session, new_line);
pthread_detach (child_thread);
- }
- else
- new_session(new_line);
#elif YAZ_GNU_THREADS
- if (control_block.threads)
- {
pth_attr_t attr;
pth_t child_thread;
child_thread = pth_spawn (attr, new_session, new_line);
yaz_log (YLOG_DEBUG, "pth_spawn finish");
pth_attr_destroy (attr);
+#else
+ new_session(new_line);
+#endif
}
else
new_session(new_line);
-#else
- new_session(new_line);
-#endif
}
else if (event == EVENT_TIMEOUT)
{
#else
a = 0;
#endif
- yaz_log(log_session, "Starting session from %s (pid=%d)",
- a ? a : "[Unknown]", getpid());
- if (max_sessions && no_sessions == max_sessions)
+ yaz_log(log_session, "Starting session %d from %s (pid=%ld)",
+ no_sessions, a ? a : "[Unknown]", (long) getpid());
+ if (max_sessions && no_sessions >= max_sessions)
control_block.one_shot = 1;
if (control_block.threads)
{
#endif
#ifdef WIN32
- sep='\\';
+ sep = '\\';
#else
- sep='/';
+ sep = '/';
#endif
if ((me = strrchr (argv[0], sep)))
me++; /* get the basename */
else
me = argv[0];
- programname=argv[0];
+ programname = argv[0];
if (control_block.options_func(argc, argv))
return(1);
inetd_connection(control_block.default_proto);
else
{
+ static int hand[2];
if (control_block.background)
{
+ /* create pipe so that parent waits until child has created
+ PID (or failed) */
+ if (pipe(hand) < 0)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "pipe");
+ return 1;
+ }
switch (fork())
{
case 0:
break;
case -1:
return 1;
- default:
- _exit(0);
+ default:
+ close(hand[1]);
+ while(1)
+ {
+ char dummy[1];
+ int res = read(hand[0], dummy, 1);
+ if (res < 0 && yaz_errno() != EINTR)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "read fork handshake");
+ break;
+ }
+ else if (res >= 0)
+ break;
+ }
+ close(hand[0]);
+ _exit(0);
}
-
+ /* child */
+ close(hand[0]);
if (setsid() < 0)
return 1;
close(0);
close(1);
close(2);
- open("/dev/null",O_RDWR);
+ open("/dev/null", O_RDWR);
dup(0); dup(0);
}
if (!pListener && *control_block.default_listen)
fclose(f);
}
- yaz_log (log_server, "Starting server %s pid=%d", programname, getpid());
+ if (control_block.background)
+ close(hand[1]);
+
+ yaz_log (log_server, "Starting server %s pid=%ld", programname,
+ (long) getpid());
#if 0
sigset_t sigs_to_block;