Commit 0ed2df12 authored by Niels Möller's avatar Niels Möller
Browse files

* src/io.c (do_consuming_read): In the EOF case, call

close_fd_read after A_WRITE.

* src/io.c (do_kill_io_backend): Let close_fd do it's work.

* src/io.c (close_fd): Really close the fd, and invoke any close
callback.
(io_iter): Simplified handling of closed files. Simply unlink
them, close_fd has to do the rest of the work.

Rev: src/io.c:1.137
parent 81901668
...@@ -161,78 +161,40 @@ int io_iter(struct io_backend *b) ...@@ -161,78 +161,40 @@ int io_iter(struct io_backend *b)
p->super.alive = 0; p->super.alive = 0;
} }
} }
/* Prepare fds. */
{ {
struct lsh_fd *fd; struct lsh_fd *fd;
int need_close;
/* Prepare fd:s. This phase calls the prepare-methods, also closes
* and unlinks any fd:s that should be closed, and also counts how
* many fd:s there are. */
for (fd = b->files; fd; fd = fd->next) for (fd = b->files; fd; fd = fd->next)
{ /* NOTE: The prepare callback is allowed to close files. */
if (fd->super.alive && fd->prepare) if (fd->super.alive && fd->prepare)
FD_PREPARE(fd); FD_PREPARE(fd);
} }
/* Note that calling a close callback might cause other files to
* be closed as well, so we need a double loop.
*
* FIXME: How can we improve this? We could keep a stack of closed
* files, but that will require backpointers from the fd:s to the
* backend (so that close_fd can find the top of the stack). */
do /* This phase unlinks any closed fd:s, and also counts how many
* fd:s there are. */
{
struct lsh_fd *fd;
struct lsh_fd **fd_p;
nfds = 0;
for(fd_p = &b->files; (fd = *fd_p); )
{ {
struct lsh_fd **fd_p; if (!fd->super.alive)
need_close = 0; /* Unlink this fd */
nfds = 0; *fd_p = fd->next;
for(fd_p = &b->files; (fd = *fd_p); ) else
{ {
if (!fd->super.alive)
{
if (fd->fd < 0)
/* Unlink the file object, but don't close any
* underlying file. */
;
else
{
/* Used by write fd:s to make sure that writing to its
* buffer fails. */
if (fd->write_close)
FD_WRITE_CLOSE(fd);
if (fd->close_callback)
{
LSH_CALLBACK(fd->close_callback);
need_close = 1;
}
trace("io.c: Closing fd %i: %z\n", fd->fd, fd->label);
if (close(fd->fd) < 0)
{
werror("io.c: close failed, (errno = %i): %z\n",
errno, STRERROR(errno));
EXCEPTION_RAISE(fd->e,
make_io_exception(EXC_IO_CLOSE, fd,
errno, NULL));
}
}
/* Unlink this fd */
*fd_p = fd->next;
continue;
}
if (fd->want_read || fd->want_write) if (fd->want_read || fd->want_write)
nfds++; nfds++;
fd_p = &fd->next; fd_p = &fd->next;
} }
} while (need_close); }
} }
if (!nfds) if (!nfds)
/* Nothing more to do. /* Nothing more to do.
* *
...@@ -449,30 +411,8 @@ do_kill_io_backend(struct resource *s) ...@@ -449,30 +411,8 @@ do_kill_io_backend(struct resource *s)
for (fd = backend->files, backend->files = NULL; for (fd = backend->files, backend->files = NULL;
fd; fd = fd->next) fd; fd = fd->next)
{ close_fd(fd);
close_fd(fd);
if (fd->fd < 0)
/* Unlink silently. */
;
else
{
if (fd->write_close)
FD_WRITE_CLOSE(fd);
if (fd->close_callback)
LSH_CALLBACK(fd->close_callback);
if (close(fd->fd) < 0)
{
werror("io.c: close failed, (errno = %i): %z\n",
errno, STRERROR(errno));
EXCEPTION_RAISE(fd->e,
make_io_exception(EXC_IO_CLOSE, fd,
errno, NULL));
}
}
}
/* Check that no callback has opened new files. */ /* Check that no callback has opened new files. */
assert(!backend->files); assert(!backend->files);
...@@ -708,8 +648,8 @@ do_consuming_read(struct io_callback *c, ...@@ -708,8 +648,8 @@ do_consuming_read(struct io_callback *c,
lsh_string_free(s); lsh_string_free(s);
eof: eof:
/* Close the fd, unless it has a write callback. */ /* Close the fd, unless it has a write callback. */
close_fd_read(fd);
A_WRITE(self->consumer, NULL); A_WRITE(self->consumer, NULL);
close_fd_read(fd);
} }
} }
} }
...@@ -1804,9 +1744,37 @@ io_read_file(struct io_backend *backend, ...@@ -1804,9 +1744,37 @@ io_read_file(struct io_backend *backend,
void close_fd(struct lsh_fd *fd) void close_fd(struct lsh_fd *fd)
{ {
trace("io.c: Marking fd %i: %z, for closing.\n", trace("io.c: Closing fd %i: %z.\n",
fd->fd, fd->label); fd->fd, fd->label);
fd->super.alive = 0;
if (fd->super.alive)
{
fd->super.alive = 0;
if (fd->fd < 0)
/* Unlink the file object, but don't close any
* underlying file. */
return;
/* Used by write fd:s to make sure that writing to its
* buffer fails. */
if (fd->write_close)
FD_WRITE_CLOSE(fd);
if (fd->close_callback)
LSH_CALLBACK(fd->close_callback);
if (close(fd->fd) < 0)
{
werror("io.c: close failed, (errno = %i): %z\n",
errno, STRERROR(errno));
EXCEPTION_RAISE(fd->e,
make_io_exception(EXC_IO_CLOSE, fd,
errno, NULL));
}
}
else
werror("Closed already.\n");
} }
void close_fd_nicely(struct lsh_fd *fd) void close_fd_nicely(struct lsh_fd *fd)
......
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