mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-03 17:56:17 +01:00
Merge branch 'fix-fileutils-test' into 'main'
Clean up Windows Invalid Parameter Handler setup and fix fileutils test Closes #2800 See merge request GNOME/glib!3036
This commit is contained in:
commit
201c920cbd
@ -24,6 +24,10 @@
|
||||
#include "glib-private.h"
|
||||
#include "glib-init.h"
|
||||
|
||||
#ifdef USE_INVALID_PARAMETER_HANDLER
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* glib__private__:
|
||||
* @arg: Do not use this argument
|
||||
@ -60,7 +64,81 @@ glib__private__ (void)
|
||||
g_win32_reopen_noninherited,
|
||||
g_win32_handle_is_socket,
|
||||
#endif
|
||||
|
||||
g_win32_push_empty_invalid_parameter_handler,
|
||||
g_win32_pop_invalid_parameter_handler,
|
||||
};
|
||||
|
||||
return &table;
|
||||
}
|
||||
|
||||
#ifdef USE_INVALID_PARAMETER_HANDLER
|
||||
/*
|
||||
* This is the (empty) invalid parameter handler
|
||||
* that is used for Visual C++ 2005 (and later) builds
|
||||
* so that we can use this instead of the system automatically
|
||||
* aborting the process, when calling _get_osfhandle(), isatty()
|
||||
* and _commit() (via g_fsync()) and so on with an invalid file
|
||||
* descriptor.
|
||||
*
|
||||
* This is necessary so that the gspawn helper and the test programs
|
||||
* will continue to run as expected, since we are purposely or
|
||||
* forced to use invalid FDs.
|
||||
*
|
||||
* Please see https://learn.microsoft.com/en-us/cpp/c-runtime-library/parameter-validation?view=msvc-170
|
||||
* for an explanation on this.
|
||||
*/
|
||||
static void
|
||||
empty_invalid_parameter_handler (const wchar_t *expression,
|
||||
const wchar_t *function,
|
||||
const wchar_t *file,
|
||||
unsigned int line,
|
||||
uintptr_t pReserved)
|
||||
{
|
||||
}
|
||||
|
||||
/* fallback to _set_invalid_parameter_handler() if we don't have _set_thread_local_invalid_parameter_handler() */
|
||||
#ifndef HAVE__SET_THREAD_LOCAL_INVALID_PARAMETER_HANDLER
|
||||
# define _set_thread_local_invalid_parameter_handler _set_invalid_parameter_handler
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*
|
||||
* g_win32_push_empty_invalid_parameter_handler:
|
||||
* @handler: a possibly uninitialized GWin32InvalidParameterHandler
|
||||
*/
|
||||
void
|
||||
g_win32_push_empty_invalid_parameter_handler (GWin32InvalidParameterHandler *handler)
|
||||
{
|
||||
#ifdef USE_INVALID_PARAMETER_HANDLER
|
||||
/* use the empty invalid parameter handler to override the default invalid parameter_handler */
|
||||
handler->pushed_handler = empty_invalid_parameter_handler;
|
||||
handler->old_handler = _set_thread_local_invalid_parameter_handler (handler->pushed_handler);
|
||||
|
||||
/* Disable the message box for assertions. */
|
||||
handler->pushed_report_mode = 0;
|
||||
handler->prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, handler->pushed_report_mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* g_win32_pop_invalid_parameter_handler:
|
||||
* @handler: a GWin32InvalidParameterHandler processed with
|
||||
* g_win32_push_empty_invalid_parameter_handler()
|
||||
*/
|
||||
void
|
||||
g_win32_pop_invalid_parameter_handler (GWin32InvalidParameterHandler *handler)
|
||||
{
|
||||
#ifdef USE_INVALID_PARAMETER_HANDLER
|
||||
G_GNUC_UNUSED _invalid_parameter_handler popped_handler;
|
||||
G_GNUC_UNUSED int popped_report_mode;
|
||||
|
||||
/* Restore previous/default invalid parameter handler, check the value returned matches the one we previously pushed */
|
||||
popped_handler = _set_thread_local_invalid_parameter_handler (handler->old_handler);
|
||||
g_return_if_fail (handler->pushed_handler == popped_handler);
|
||||
|
||||
/* Restore the message box for assertions, check the value returned matches the one we previously pushed */
|
||||
popped_report_mode = _CrtSetReportMode(_CRT_ASSERT, handler->prev_report_mode);
|
||||
g_return_if_fail (handler->pushed_report_mode == popped_report_mode);
|
||||
#endif
|
||||
}
|
||||
|
@ -121,6 +121,27 @@ GMainContext * g_get_worker_context (void);
|
||||
gboolean g_check_setuid (void);
|
||||
GMainContext * g_main_context_new_with_next_id (guint next_id);
|
||||
|
||||
#if (defined (HAVE__SET_THREAD_LOCAL_INVALID_PARAMETER_HANDLER) || \
|
||||
defined (HAVE__SET_INVALID_PARAMETER_HANDLER)) && \
|
||||
defined (HAVE__CRT_SET_REPORT_MODE)
|
||||
# define USE_INVALID_PARAMETER_HANDLER
|
||||
#endif
|
||||
|
||||
#ifdef USE_INVALID_PARAMETER_HANDLER
|
||||
struct _GWin32InvalidParameterHandler
|
||||
{
|
||||
_invalid_parameter_handler old_handler;
|
||||
_invalid_parameter_handler pushed_handler;
|
||||
int prev_report_mode;
|
||||
int pushed_report_mode;
|
||||
};
|
||||
#else
|
||||
struct _GWin32InvalidParameterHandler
|
||||
{
|
||||
int unused_really;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gchar *_glib_get_locale_dir (void);
|
||||
@ -129,8 +150,13 @@ gchar *_glib_get_locale_dir (void);
|
||||
GDir * g_dir_open_with_errno (const gchar *path, guint flags);
|
||||
GDir * g_dir_new_from_dirp (gpointer dirp);
|
||||
|
||||
typedef struct _GWin32InvalidParameterHandler GWin32InvalidParameterHandler;
|
||||
void g_win32_push_empty_invalid_parameter_handler (GWin32InvalidParameterHandler *items);
|
||||
void g_win32_pop_invalid_parameter_handler (GWin32InvalidParameterHandler *items);
|
||||
|
||||
#define GLIB_PRIVATE_CALL(symbol) (glib__private__()->symbol)
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* See gwakeup.c */
|
||||
GWakeup * (* g_wakeup_new) (void);
|
||||
@ -182,6 +208,10 @@ typedef struct {
|
||||
|
||||
#endif
|
||||
|
||||
/* See glib-private.c */
|
||||
void (* g_win32_push_empty_invalid_parameter_handler) (GWin32InvalidParameterHandler *items);
|
||||
|
||||
void (* g_win32_pop_invalid_parameter_handler) (GWin32InvalidParameterHandler *items);
|
||||
|
||||
/* Add other private functions here, initialize them in glib-private.c */
|
||||
} GLibPrivateVTable;
|
||||
|
@ -192,6 +192,7 @@
|
||||
#include "gcharset.h"
|
||||
#include "gconvert.h"
|
||||
#include "genviron.h"
|
||||
#include "glib-private.h"
|
||||
#include "gmain.h"
|
||||
#include "gmem.h"
|
||||
#include "gprintfint.h"
|
||||
@ -219,22 +220,6 @@
|
||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||
#endif
|
||||
|
||||
#if defined (_MSC_VER) && (_MSC_VER >=1400)
|
||||
/* This is ugly, but we need it for isatty() in case we have bad fd's,
|
||||
* otherwise Windows will abort() the program on msvcrt80.dll and later
|
||||
*/
|
||||
#include <crtdbg.h>
|
||||
|
||||
_GLIB_EXTERN void
|
||||
myInvalidParameterHandler(const wchar_t *expression,
|
||||
const wchar_t *function,
|
||||
const wchar_t *file,
|
||||
unsigned int line,
|
||||
uintptr_t pReserved)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "gwin32.h"
|
||||
#endif
|
||||
|
||||
@ -2111,12 +2096,7 @@ g_log_writer_supports_color (gint output_fd)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
gboolean result = FALSE;
|
||||
|
||||
#if (defined (_MSC_VER) && _MSC_VER >= 1400)
|
||||
_invalid_parameter_handler oldHandler, newHandler;
|
||||
int prev_report_mode = 0;
|
||||
#endif
|
||||
|
||||
GWin32InvalidParameterHandler handler;
|
||||
#endif
|
||||
|
||||
g_return_val_if_fail (output_fd >= 0, FALSE);
|
||||
@ -2143,17 +2123,7 @@ g_log_writer_supports_color (gint output_fd)
|
||||
*/
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
#if (defined (_MSC_VER) && _MSC_VER >= 1400)
|
||||
/* Set up our empty invalid parameter handler, for isatty(),
|
||||
* in case of bad fd's passed in for isatty(), so that
|
||||
* msvcrt80.dll+ won't abort the program
|
||||
*/
|
||||
newHandler = myInvalidParameterHandler;
|
||||
oldHandler = _set_invalid_parameter_handler (newHandler);
|
||||
|
||||
/* Disable the message box for assertions. */
|
||||
prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, 0);
|
||||
#endif
|
||||
g_win32_push_empty_invalid_parameter_handler (&handler);
|
||||
|
||||
if (g_win32_check_windows_version (10, 0, 0, G_WIN32_OS_ANY))
|
||||
{
|
||||
@ -2185,10 +2155,7 @@ g_log_writer_supports_color (gint output_fd)
|
||||
result = win32_is_pipe_tty (output_fd);
|
||||
|
||||
reset_invalid_param_handler:
|
||||
#if defined (_MSC_VER) && (_MSC_VER >= 1400)
|
||||
_CrtSetReportMode(_CRT_ASSERT, prev_report_mode);
|
||||
_set_invalid_parameter_handler (oldHandler);
|
||||
#endif
|
||||
g_win32_pop_invalid_parameter_handler (&handler);
|
||||
|
||||
return result;
|
||||
#else
|
||||
|
@ -23,20 +23,6 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
/* For _CrtSetReportMode, we don't want Windows CRT (2005 and later)
|
||||
* to terminate the process if a bad file descriptor is passed into
|
||||
* _get_osfhandle(). This is necessary because we use _get_osfhandle()
|
||||
* to check the validity of the fd before we try to call close() on
|
||||
* it as attempting to close an invalid fd will cause the Windows CRT
|
||||
* to abort() this program internally.
|
||||
*
|
||||
* Please see http://msdn.microsoft.com/zh-tw/library/ks2530z6%28v=vs.80%29.aspx
|
||||
* for an explanation on this.
|
||||
*/
|
||||
#if (defined (_MSC_VER) && _MSC_VER >= 1400)
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#include "glib.h"
|
||||
#define GSPAWN_HELPER
|
||||
@ -168,30 +154,6 @@ checked_dup2 (int oldfd, int newfd, int report_fd)
|
||||
return newfd;
|
||||
}
|
||||
|
||||
#if (defined (_MSC_VER) && _MSC_VER >= 1400)
|
||||
/*
|
||||
* This is the (empty) invalid parameter handler
|
||||
* that is used for Visual C++ 2005 (and later) builds
|
||||
* so that we can use this instead of the system automatically
|
||||
* aborting the process.
|
||||
*
|
||||
* This is necessary as we use _get_oshandle() to check the validity
|
||||
* of the file descriptors as we close them, so when an invalid file
|
||||
* descriptor is passed into that function as we check on it, we get
|
||||
* -1 as the result, instead of the gspawn helper program aborting.
|
||||
*
|
||||
* Please see http://msdn.microsoft.com/zh-tw/library/ks2530z6%28v=vs.80%29.aspx
|
||||
* for an explanation on this.
|
||||
*/
|
||||
extern void
|
||||
myInvalidParameterHandler(const wchar_t *expression,
|
||||
const wchar_t *function,
|
||||
const wchar_t *file,
|
||||
unsigned int line,
|
||||
uintptr_t pReserved);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HELPER_CONSOLE
|
||||
int _stdcall
|
||||
WinMain (struct HINSTANCE__ *hInstance,
|
||||
@ -220,16 +182,7 @@ main (int ignored_argc, char **ignored_argv)
|
||||
char **argv;
|
||||
wchar_t **wargv;
|
||||
char c;
|
||||
|
||||
#if (defined (_MSC_VER) && _MSC_VER >= 1400)
|
||||
/* set up our empty invalid parameter handler */
|
||||
_invalid_parameter_handler oldHandler, newHandler;
|
||||
newHandler = myInvalidParameterHandler;
|
||||
oldHandler = _set_invalid_parameter_handler(newHandler);
|
||||
|
||||
/* Disable the message box for assertions. */
|
||||
_CrtSetReportMode(_CRT_ASSERT, 0);
|
||||
#endif
|
||||
GWin32InvalidParameterHandler handler;
|
||||
|
||||
/* Fetch the wide-char argument vector */
|
||||
wargv = CommandLineToArgvW (GetCommandLineW(), &argc);
|
||||
@ -398,11 +351,13 @@ main (int ignored_argc, char **ignored_argv)
|
||||
/* argv[ARG_CLOSE_DESCRIPTORS] is "y" if file descriptors from 3
|
||||
* upwards should be closed
|
||||
*/
|
||||
GLIB_PRIVATE_CALL (g_win32_push_empty_invalid_parameter_handler) (&handler);
|
||||
if (argv[ARG_CLOSE_DESCRIPTORS][0] == 'y')
|
||||
for (i = 3; i < 1000; i++) /* FIXME real limit? */
|
||||
if (!g_hash_table_contains (fds, GINT_TO_POINTER (i)))
|
||||
if (_get_osfhandle (i) != -1)
|
||||
close (i);
|
||||
GLIB_PRIVATE_CALL (g_win32_pop_invalid_parameter_handler) (&handler);
|
||||
|
||||
/* We don't want our child to inherit the error report and
|
||||
* helper sync fds.
|
||||
|
@ -35,6 +35,7 @@
|
||||
/* Test our stdio wrappers here; this disables redefining (e.g.) g_open() to open() */
|
||||
#define G_STDIO_WRAP_ON_UNIX
|
||||
#include <glib/gstdio.h>
|
||||
#include "glib-private.h"
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
#include <unistd.h>
|
||||
@ -2462,8 +2463,13 @@ assert_fd_was_closed (int fd)
|
||||
* was still valid */
|
||||
if (g_test_undefined ())
|
||||
{
|
||||
int result = g_fsync (fd);
|
||||
int errsv = errno;
|
||||
int result, errsv;
|
||||
GWin32InvalidParameterHandler handler;
|
||||
|
||||
GLIB_PRIVATE_CALL (g_win32_push_empty_invalid_parameter_handler) (&handler);
|
||||
result = g_fsync (fd);
|
||||
errsv = errno;
|
||||
GLIB_PRIVATE_CALL (g_win32_pop_invalid_parameter_handler) (&handler);
|
||||
|
||||
g_assert_cmpint (result, !=, 0);
|
||||
g_assert_cmpint (errsv, ==, EBADF);
|
||||
|
@ -26,10 +26,7 @@ glib_tests = {
|
||||
'can_fail' : host_system == 'darwin',
|
||||
},
|
||||
'error' : {},
|
||||
'fileutils' : {
|
||||
# FIXME: https://gitlab.gnome.org/GNOME/glib/-/issues/2800
|
||||
'can_fail' : host_system == 'windows' and cc.get_id() == 'msvc',
|
||||
},
|
||||
'fileutils' : {},
|
||||
'gdatetime' : {
|
||||
'suite' : ['slow'],
|
||||
'can_fail' : host_system == 'windows',
|
||||
|
14
meson.build
14
meson.build
@ -2373,6 +2373,20 @@ install_data('m4macros/glib-2.0.m4', 'm4macros/glib-gettext.m4', 'm4macros/gsett
|
||||
install_tag : 'devel',
|
||||
)
|
||||
|
||||
# Check whether we support overriding the invalid parameter handler on Windows for _get_osfhandle(),
|
||||
# g_fsync() (i.e. _commit()), etc
|
||||
if host_system == 'windows'
|
||||
if cc.has_function('_set_thread_local_invalid_parameter_handler', prefix: '#include <stdlib.h>')
|
||||
glib_conf.set('HAVE__SET_THREAD_LOCAL_INVALID_PARAMETER_HANDLER', 1)
|
||||
endif
|
||||
if cc.has_function('_set_invalid_parameter_handler', prefix: '#include <stdlib.h>')
|
||||
glib_conf.set('HAVE__SET_INVALID_PARAMETER_HANDLER', 1)
|
||||
endif
|
||||
if cc.has_header_symbol('crtdbg.h', '_CrtSetReportMode')
|
||||
glib_conf.set('HAVE__CRT_SET_REPORT_MODE', 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
configure_file(output : 'config.h', configuration : glib_conf)
|
||||
|
||||
if host_system == 'windows'
|
||||
|
Loading…
Reference in New Issue
Block a user