genode/repos/libports/src/lib/libc/plugin.cc
Norman Feske cd92b32622 libc: close all open FDs on exit
This is important to issue sync requests for written-to files.

As the closing must be performed by an atexit handler, it happens at a
time _after_ libc plugins are destructed. Consequently an FD allocated
by such a plugin results in a close error, which in turn, does not
destruct the FD. We ultimatedly end up in an infinte loop of
re-attempting the close. For this reason, the patch changes 'close' to
be robust against this special case.

This is generally not a problem because libc plugins are phased out.
However, at present, the libc_noux plugin is still important. With the
changed 'close' in place, there occurred an error message "Error: close:
close not implemented" at the exit of each noux program. This patch
removes the error printing from the libc plugin mechansim to avoid this
noise. The error messages are not important anyway because the
deprecation of the libc plugin interface.

Issue #3578
2019-12-19 17:00:48 +01:00

219 lines
5.4 KiB
C++

/*
* \brief Plugin implementation
* \author Christian Prochaska
* \date 2010-01-21
*/
/*
* Copyright (C) 2010-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <base/log.h>
/* libc plugin interface */
#include <libc-plugin/fd_alloc.h>
#include <libc-plugin/plugin_registry.h>
#include <libc-plugin/plugin.h>
/* local includes */
#include <internal/init.h>
#include <internal/resume.h>
using namespace Libc;
static Resume *_resume_ptr;
void Libc::init_plugin(Resume &resume)
{
_resume_ptr = &resume;
}
void Plugin::resume_all()
{
struct Missing_call_of_init_plugin : Exception { };
if (!_resume_ptr)
throw Missing_call_of_init_plugin();
_resume_ptr->resume_all();
}
Plugin::Plugin(int priority)
: _priority(priority)
{
plugin_registry()->insert(this);
}
Plugin::~Plugin()
{
plugin_registry()->remove(this);
}
int Plugin::priority()
{
return _priority;
}
bool Plugin::supports_access(char const *path, int amode)
{
return false;
}
bool Plugin::supports_mkdir(const char *, mode_t)
{
return false;
}
bool Plugin::supports_open(const char *, int)
{
return false;
}
bool Plugin::supports_pipe()
{
return false;
}
bool Plugin::supports_poll()
{
return false;
}
bool Plugin::supports_readlink(const char *path, char *buf, ::size_t bufsiz)
{
return false;
}
bool Plugin::supports_rename(const char *, const char *)
{
return false;
}
bool Plugin::supports_rmdir(const char*)
{
return false;
}
bool Plugin::supports_select(int, fd_set *, fd_set *,
fd_set *, struct timeval *)
{
return false;
}
bool Plugin::supports_socket(int, int, int)
{
return false;
}
bool Plugin::supports_stat(const char*)
{
return false;
}
bool Plugin::supports_symlink(const char*, const char *)
{
return false;
}
bool Plugin::supports_unlink(const char*)
{
return false;
}
bool Plugin::supports_mmap()
{
return false;
}
/**
* Generate dummy member function of Plugin class
*/
#define DUMMY(ret_type, ret_val, name, args) \
ret_type Plugin::name args \
{ \
return ret_val; \
}
/*
* Functions returning a 'File_descriptor'
*/
DUMMY(File_descriptor *, 0, dup, (File_descriptor *));
DUMMY(File_descriptor *, 0, open, (const char *, int));
DUMMY(File_descriptor *, 0, socket, (int, int, int));
DUMMY(File_descriptor *, 0, accept, (File_descriptor *, struct sockaddr *, socklen_t *));
/*
* Functions taking a file descriptor as first argument
*/
DUMMY(int, -1, bind, (File_descriptor *, const struct sockaddr *, socklen_t));
DUMMY(int, -1, close, (File_descriptor *));
DUMMY(int, -1, connect, (File_descriptor *, const struct sockaddr *, socklen_t));
DUMMY(int, -1, dup2, (File_descriptor *, File_descriptor *new_fd));
DUMMY(int, -1, fstatfs, (File_descriptor *, struct statfs *));
DUMMY(int, -1, fcntl, (File_descriptor *, int cmd, long arg));
DUMMY(int, -1, fstat, (File_descriptor *, struct stat *));
DUMMY(int, -1, fsync, (File_descriptor *));
DUMMY(int, -1, ftruncate, (File_descriptor *, ::off_t));
DUMMY(ssize_t, -1, getdirentries, (File_descriptor *, char *, ::size_t, ::off_t *));
DUMMY(int, -1, getpeername, (File_descriptor *, struct sockaddr *, socklen_t *));
DUMMY(int, -1, getsockname, (File_descriptor *, struct sockaddr *, socklen_t *));
DUMMY(int, -1, getsockopt, (File_descriptor *, int, int, void *, socklen_t *));
DUMMY(int, -1, ioctl, (File_descriptor *, int, char*));
DUMMY(int, -1, listen, (File_descriptor *, int));
DUMMY(::off_t, -1, lseek, (File_descriptor *, ::off_t, int));
DUMMY(ssize_t, -1, read, (File_descriptor *, void *, ::size_t));
DUMMY(ssize_t, -1, recv, (File_descriptor *, void *, ::size_t, int));
DUMMY(ssize_t, -1, recvfrom, (File_descriptor *, void *, ::size_t, int, struct sockaddr *, socklen_t *));
DUMMY(ssize_t, -1, recvmsg, (File_descriptor *, struct msghdr *, int));
DUMMY(ssize_t, -1, send, (File_descriptor *, const void *, ::size_t, int));
DUMMY(ssize_t, -1, sendto, (File_descriptor *, const void *, ::size_t, int, const struct sockaddr *, socklen_t));
DUMMY(int, -1, setsockopt, (File_descriptor *, int, int, const void *, socklen_t));
DUMMY(int, -1, shutdown, (File_descriptor *, int));
DUMMY(ssize_t, -1, write, (File_descriptor *, const void *, ::size_t));
/*
* Misc
*/
DUMMY(int, -1, access, (char const *, int));
DUMMY(int, -1, mkdir, (const char*, mode_t));
DUMMY(void *, (void *)(-1), mmap, (void *addr, ::size_t length, int prot, int flags,
File_descriptor *, ::off_t offset));
DUMMY(int, -1, munmap, (void *, ::size_t));
DUMMY(int, -1, msync, (void *addr, ::size_t len, int flags));
DUMMY(int, -1, pipe, (File_descriptor*[2]));
DUMMY(bool, 0, poll, (File_descriptor &, struct pollfd &));
DUMMY(ssize_t, -1, readlink, (const char *, char *, ::size_t));
DUMMY(int, -1, rename, (const char *, const char *));
DUMMY(int, -1, rmdir, (const char*));
DUMMY(int, -1, select, (int, fd_set *, fd_set *, fd_set *, struct timeval *));
DUMMY(int, -1, stat, (const char*, struct stat*));
DUMMY(int, -1, symlink, (const char*, const char*));
DUMMY(int, -1, unlink, (const char*));