Commit 79af12ae authored by Niels Möller's avatar Niels Möller
Browse files

(nfiles): New global variable.

(lsh_oop_stop_callback): New function.
(lsh_oop_stop): New function.
(lsh_oop_cancel_stop): New function.
(io_nfiles): New function.
(close_fd): Decrement nfiles, and call lsh_oop_stop when no files
are left.
(make_lsh_fd): Increment nfiles.

Rev: src/io.c:1.160
Rev: src/io.h:1.88
parent 59be36d5
...@@ -75,55 +75,7 @@ ...@@ -75,55 +75,7 @@
/* Because of signal handlers, there can be only one oop object. */ /* Because of signal handlers, there can be only one oop object. */
static oop_source_sys *global_oop_sys = NULL; static oop_source_sys *global_oop_sys = NULL;
static oop_source *source = NULL; static oop_source *source = NULL;
static unsigned nfiles = 0;
void
io_init(void)
{
struct sigaction pipe;
memset(&pipe, 0, sizeof(pipe));
pipe.sa_handler = SIG_IGN;
sigemptyset(&pipe.sa_mask);
pipe.sa_flags = 0;
if (sigaction(SIGPIPE, &pipe, NULL) < 0)
fatal("Failed to ignore SIGPIPE.\n");
assert(!global_oop_sys);
global_oop_sys = oop_sys_new();
if (!global_oop_sys)
fatal("Failed to initialize liboop.\n");
source = oop_sys_source(global_oop_sys);
}
void
io_final(void)
{
assert(source);
gc_final();
/* There mustn't be any outstanding callbacks left. */
oop_sys_delete(global_oop_sys);
global_oop_sys = NULL;
source = NULL;
}
void
io_run(void)
{
void *res = oop_sys_run(global_oop_sys);
/* FIXME: OOP_ERROR is not defined in liboop-0.7. Upgrade, and then
* enable this check. */
#if 0
if (res == OOP_ERROR)
werror("oop_sys_run (errno = %i): %z\n",
errno, STRERROR(errno));
#endif
trace("io_run: Exiting\n");
}
/* OOP Callbacks */ /* OOP Callbacks */
static void * static void *
...@@ -149,7 +101,8 @@ lsh_oop_register_signal(struct lsh_signal_handler *handler) ...@@ -149,7 +101,8 @@ lsh_oop_register_signal(struct lsh_signal_handler *handler)
assert(source); assert(source);
if (handler->super.alive) if (handler->super.alive)
source->on_signal(source, handler->signum, lsh_oop_signal_callback, handler); source->on_signal(source, handler->signum,
lsh_oop_signal_callback, handler);
} }
static void static void
...@@ -160,11 +113,13 @@ lsh_oop_cancel_signal(struct lsh_signal_handler *handler) ...@@ -160,11 +113,13 @@ lsh_oop_cancel_signal(struct lsh_signal_handler *handler)
assert(source); assert(source);
if (handler->super.alive) if (handler->super.alive)
source->cancel_signal(source, handler->signum, lsh_oop_signal_callback, handler); source->cancel_signal(source, handler->signum,
lsh_oop_signal_callback, handler);
} }
static void * static void *
lsh_oop_fd_read_callback(oop_source *s UNUSED, int fileno, oop_event event, void *data) lsh_oop_fd_read_callback(oop_source *s UNUSED, int fileno,
oop_event event, void *data)
{ {
CAST(lsh_fd, fd, (struct lsh_object *) data); CAST(lsh_fd, fd, (struct lsh_object *) data);
...@@ -211,7 +166,8 @@ lsh_oop_cancel_read_fd(struct lsh_fd *fd) ...@@ -211,7 +166,8 @@ lsh_oop_cancel_read_fd(struct lsh_fd *fd)
} }
static void * static void *
lsh_oop_fd_write_callback(oop_source *s UNUSED, int fileno, oop_event event, void *data) lsh_oop_fd_write_callback(oop_source *s UNUSED, int fileno,
oop_event event, void *data)
{ {
CAST(lsh_fd, fd, (struct lsh_object *) data); CAST(lsh_fd, fd, (struct lsh_object *) data);
...@@ -296,6 +252,86 @@ lsh_oop_cancel_callout(struct lsh_callout *callout) ...@@ -296,6 +252,86 @@ lsh_oop_cancel_callout(struct lsh_callout *callout)
source->cancel_time(source, callout->when, lsh_oop_time_callback, callout); source->cancel_time(source, callout->when, lsh_oop_time_callback, callout);
} }
static void *
lsh_oop_stop_callback(oop_source *source UNUSED,
struct timeval time UNUSED, void *data UNUSED)
{
trace("lsh_oop_stop_callback\n");
if (!nfiles)
/* An arbitrary non-NULL value stops oop_sys_run. */
return &nfiles;
else
return OOP_CONTINUE;
}
static void
lsh_oop_stop(void)
{
assert(source);
trace("lsh_oop_stop\n");
source->on_time(source, OOP_TIME_NOW, lsh_oop_stop_callback, NULL);
}
static void
lsh_oop_cancel_stop(void)
{
assert(source);
trace("lsh_oop_cancel_stop\n");
source->cancel_time(source, OOP_TIME_NOW, lsh_oop_stop_callback, NULL);
}
void
io_init(void)
{
struct sigaction pipe;
memset(&pipe, 0, sizeof(pipe));
pipe.sa_handler = SIG_IGN;
sigemptyset(&pipe.sa_mask);
pipe.sa_flags = 0;
if (sigaction(SIGPIPE, &pipe, NULL) < 0)
fatal("Failed to ignore SIGPIPE.\n");
assert(!global_oop_sys);
global_oop_sys = oop_sys_new();
if (!global_oop_sys)
fatal("Failed to initialize liboop.\n");
source = oop_sys_source(global_oop_sys);
}
void
io_final(void)
{
assert(source);
gc_final();
/* The final gc may have closed some files, and called lsh_oop_stop.
* So we must unregister that before deleting the oop source. */
lsh_oop_cancel_stop();
/* There mustn't be any outstanding callbacks left. */
oop_sys_delete(global_oop_sys);
global_oop_sys = NULL;
source = NULL;
}
void
io_run(void)
{
void *res = oop_sys_run(global_oop_sys);
/* We need liboop-0.8, OOP_ERROR is not defined in liboop-0.7. */
if (res == OOP_ERROR)
werror("oop_sys_run (errno = %i): %z\n",
errno, STRERROR(errno));
trace("io_run: Exiting\n");
}
/* Calls trigged by a signal handler. */ /* Calls trigged by a signal handler. */
/* GABA: /* GABA:
...@@ -307,7 +343,6 @@ lsh_oop_cancel_callout(struct lsh_callout *callout) ...@@ -307,7 +343,6 @@ lsh_oop_cancel_callout(struct lsh_callout *callout)
(action object lsh_callback))) (action object lsh_callback)))
*/ */
/* Scheduled calls. FIXME: For now, no scheduling in time. */
/* GABA: /* GABA:
(class (class
(name lsh_callout) (name lsh_callout)
...@@ -1241,6 +1276,7 @@ make_lsh_fd(int fd, const char *label, ...@@ -1241,6 +1276,7 @@ make_lsh_fd(int fd, const char *label,
{ {
NEW(lsh_fd, self); NEW(lsh_fd, self);
nfiles++;
io_init_fd(fd); io_init_fd(fd);
init_resource(&self->super, do_kill_fd); init_resource(&self->super, do_kill_fd);
...@@ -1262,6 +1298,12 @@ make_lsh_fd(int fd, const char *label, ...@@ -1262,6 +1298,12 @@ make_lsh_fd(int fd, const char *label,
return self; return self;
} }
unsigned
io_nfiles(void)
{
return nfiles;
}
/* Some code is taken from Thomas Bellman's tcputils. */ /* Some code is taken from Thomas Bellman's tcputils. */
struct lsh_fd * struct lsh_fd *
io_connect(struct sockaddr *remote, io_connect(struct sockaddr *remote,
...@@ -1685,6 +1727,9 @@ close_fd(struct lsh_fd *fd) ...@@ -1685,6 +1727,9 @@ close_fd(struct lsh_fd *fd)
make_io_exception(EXC_IO_CLOSE, fd, make_io_exception(EXC_IO_CLOSE, fd,
errno, NULL)); errno, NULL));
} }
assert(nfiles);
if (!--nfiles)
lsh_oop_stop();
} }
else else
werror("Closed already.\n"); werror("Closed already.\n");
......
...@@ -108,6 +108,9 @@ ...@@ -108,6 +108,9 @@
#define FD_READ(fd) IO_CALLBACK((fd)->read, (fd)) #define FD_READ(fd) IO_CALLBACK((fd)->read, (fd))
#define FD_WRITE(fd) IO_CALLBACK((fd)->write, (fd)) #define FD_WRITE(fd) IO_CALLBACK((fd)->write, (fd))
/* Returns the number of open files. */
unsigned
io_nfiles(void);
/* Used for read handlers like read_line and read_packet that /* Used for read handlers like read_line and read_packet that
* processes a little data at a time, possibly replacing the handler * processes a little data at a time, possibly replacing the handler
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment