mirror of
https://github.com/flatpak/flatpak.git
synced 2026-06-26 09:17:00 -04:00
backports, local-alloc: Provide a backport of g_autofd
The functionality that was prototyped in libglnx as glnx_fd_close
and then glnx_autofd was later added to GLib as g_autofd.
glnx_close_fd() doesn't have a direct equivalent in GLib, so keep
it intact, but using the backported _glnx_clear_fd_ignore_error as
its implementation. g_clear_fd() is the closest thing in GLib, but
g_clear_fd() guarantees to set errno on failure (making it useful for
error-checking), whereas glnx_close_fd() guarantees to leave errno
untouched, making it more useful for cleanup code paths that recover
from a syscall or similar function that sets errno:
int fd = ...;
success = (fsync (fd) == 0);
glnx_close_fd (&fd);
return success; /* if false, errno indicates why fsync failed */
(Of course in many cases, including this simple example, it would have
been easier to use g_autofd.)
glnx_autofd and glnx_fd_close are now equivalent to the backport of
g_autofd, so document them as deprecated. There's essentially no cost to
retaining them, so don't apply deprecation attributes.
Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
@@ -82,6 +82,27 @@ g_clear_fd (int *fd_ptr,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is part of the backport of g_autofd, but we define it
|
||||
* unconditionally because it's also used to implement glnx_close_fd() */
|
||||
static inline void
|
||||
_glnx_clear_fd_ignore_error (int *fd_ptr)
|
||||
{
|
||||
/* Don't overwrite thread-local errno if closing the fd fails */
|
||||
int errsv = errno;
|
||||
|
||||
if (!g_clear_fd (fd_ptr, NULL))
|
||||
{
|
||||
/* Do nothing: we ignore all errors, except for EBADF which
|
||||
* is a programming error, checked for by g_close(). */
|
||||
}
|
||||
|
||||
errno = errsv;
|
||||
}
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 76, 0)
|
||||
#define g_autofd __attribute__((cleanup(_glnx_clear_fd_ignore_error)))
|
||||
#endif
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 40, 0)
|
||||
#define g_info(...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
@@ -51,38 +51,23 @@ glnx_local_obj_unref (void *v)
|
||||
* glnx_close_fd:
|
||||
* @fdp: Pointer to fd
|
||||
*
|
||||
* Effectively `close (g_steal_fd (&fd))`. Also
|
||||
* asserts that `close()` did not raise `EBADF` - encountering
|
||||
* that error is usually a critical bug in the program.
|
||||
* Same as `g_clear_fd()`, but ignoring the error (if any) and making sure
|
||||
* not to alter `errno`. As a result, this function can be used for cleanup
|
||||
* in contexts where `errno` needs to be preserved.
|
||||
*/
|
||||
static inline void
|
||||
glnx_close_fd (int *fdp)
|
||||
{
|
||||
int errsv;
|
||||
|
||||
g_assert (fdp);
|
||||
|
||||
int fd = g_steal_fd (fdp);
|
||||
if (fd >= 0)
|
||||
{
|
||||
errsv = errno;
|
||||
if (close (fd) < 0)
|
||||
g_assert (errno != EBADF);
|
||||
errno = errsv;
|
||||
}
|
||||
}
|
||||
#define glnx_close_fd _glnx_clear_fd_ignore_error
|
||||
|
||||
/**
|
||||
* glnx_fd_close:
|
||||
*
|
||||
* Deprecated in favor of `glnx_autofd`.
|
||||
* Deprecated in favor of `g_autofd`.
|
||||
*/
|
||||
#define glnx_fd_close __attribute__((cleanup(glnx_close_fd)))
|
||||
#define glnx_fd_close g_autofd
|
||||
/**
|
||||
* glnx_autofd:
|
||||
*
|
||||
* Call close() on a variable location when it goes out of scope.
|
||||
* Deprecated in favor of `g_autofd`.
|
||||
*/
|
||||
#define glnx_autofd __attribute__((cleanup(glnx_close_fd)))
|
||||
#define glnx_autofd g_autofd
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
Reference in New Issue
Block a user