* 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.17 2005-01-03 11:56:08 adam Exp $
*/
/**
#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 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)
{
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;