Fixes bug 45295.
Signed-off-by: Fabian Maurer dark.shadow4@web.de --- .../api-ms-win-crt-runtime-l1-1-0.spec | 2 +- dlls/msvcrt/exit.c | 10 +++++++++- dlls/ucrtbase/ucrtbase.spec | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec index 24014a65ba..4bc8df768d 100644 --- a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec +++ b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec @@ -28,7 +28,7 @@ @ cdecl _control87(long long) ucrtbase._control87 @ cdecl _controlfp(long long) ucrtbase._controlfp @ cdecl _controlfp_s(ptr long long) ucrtbase._controlfp_s -@ stub _crt_at_quick_exit +@ cdecl _crt_at_quick_exit(ptr) ucrtbase._crt_at_quick_exit @ cdecl _crt_atexit(ptr) ucrtbase._crt_atexit @ cdecl _crt_debugger_hook(long) ucrtbase._crt_debugger_hook @ cdecl _endthread() ucrtbase._endthread diff --git a/dlls/msvcrt/exit.c b/dlls/msvcrt/exit.c index 7e1805569c..bba2a653ed 100644 --- a/dlls/msvcrt/exit.c +++ b/dlls/msvcrt/exit.c @@ -348,6 +348,15 @@ int CDECL MSVCRT_atexit(void (*func)(void)) return MSVCRT__onexit((MSVCRT__onexit_t)func) == (MSVCRT__onexit_t)func ? 0 : -1; }
+/********************************************************************* + * _crt_at_quick_exit (UCRTBASE.@) + */ +int CDECL MSVCRT__crt_at_quick_exit(void (*func)(void)) +{ + FIXME("stub: (%p)\n", func); + return 0; +} + #if _MSVCR_VER>=140
/********************************************************************* @@ -359,7 +368,6 @@ int CDECL MSVCRT__crt_atexit(void (*func)(void)) return MSVCRT__onexit((MSVCRT__onexit_t)func) == (MSVCRT__onexit_t)func ? 0 : -1; }
- /********************************************************************* * _initialize_onexit_table (UCRTBASE.@) */ diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 236b0d526d..3cb355506a 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -240,7 +240,7 @@ @ cdecl _cputws(wstr) @ cdecl _creat(str long) MSVCRT__creat @ cdecl _create_locale(long str) MSVCRT__create_locale -@ stub _crt_at_quick_exit +@ cdecl _crt_at_quick_exit(ptr) MSVCRT__crt_at_quick_exit @ cdecl _crt_atexit(ptr) MSVCRT__crt_atexit @ cdecl _crt_debugger_hook(long) MSVCRT__crt_debugger_hook @ cdecl _ctime32(ptr) MSVCRT__ctime32
Follow-up issue to bug 45295.
Signed-off-by: Fabian Maurer dark.shadow4@web.de --- .../api-ms-win-crt-runtime-l1-1-0.spec | 2 +- dlls/msvcrt/exit.c | 10 ++++++++++ dlls/ucrtbase/ucrtbase.spec | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec index 4bc8df768d..74d682b33b 100644 --- a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec +++ b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec @@ -97,7 +97,7 @@ @ cdecl fesetround(long) ucrtbase.fesetround @ stub fetestexcept @ cdecl perror(str) ucrtbase.perror -@ stub quick_exit +@ cdecl quick_exit(long) ucrtbase.quick_exit @ cdecl raise(long) ucrtbase.raise @ cdecl set_terminate(ptr) ucrtbase.set_terminate @ cdecl signal(long long) ucrtbase.signal diff --git a/dlls/msvcrt/exit.c b/dlls/msvcrt/exit.c index bba2a653ed..313a06ecd0 100644 --- a/dlls/msvcrt/exit.c +++ b/dlls/msvcrt/exit.c @@ -120,6 +120,16 @@ void CDECL MSVCRT__exit(int exitcode) ExitProcess(exitcode); }
+/********************************************************************* + * quick_exit (MSVCRT.@) + */ +void CDECL MSVCRT_quick_exit(int exitcode) +{ + FIXME("partial stub: (%d)\n", exitcode); + MSVCRT__exit(exitcode); +} + + /* Print out an error message with an option to debug */ static void DoMessageBoxW(const MSVCRT_wchar_t *lead, const MSVCRT_wchar_t *message) { diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 3cb355506a..9d993e90b7 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -2454,7 +2454,7 @@ @ cdecl putwchar(long) MSVCRT__fputwchar @ cdecl qsort(ptr long long ptr) MSVCRT_qsort @ cdecl qsort_s(ptr long long ptr ptr) MSVCRT_qsort_s -@ stub quick_exit +@ cdecl quick_exit(long) MSVCRT_quick_exit @ cdecl raise(long) MSVCRT_raise @ cdecl rand() MSVCRT_rand @ cdecl rand_s(ptr) MSVCRT_rand_s
Hi,
On 06/05/18 22:42, Fabian Maurer wrote:
+/*********************************************************************
quick_exit (MSVCRT.@)
- */
+void CDECL MSVCRT_quick_exit(int exitcode) +{
- FIXME("partial stub: (%d)\n", exitcode);
- MSVCRT__exit(exitcode);
+}
quick_exit function should not call exit. I'm attaching a test that shows that atexit callbacks should not be called.
Thanks, Piotr
quick_exit function should not call exit. I'm attaching a test that shows that atexit callbacks should not be called.
I know, and MSVCRT__exit only calls ExitProcess, not calling any callbacks.
Regards, Fabian Maurer
On 06/12/18 09:40, Fabian Maurer wrote:
quick_exit function should not call exit. I'm attaching a test that
shows that atexit callbacks should not be called.
I know, and MSVCRT__exit only calls ExitProcess, not calling any callbacks.
I've misread the patch, sorry for that (MSVCRT_exit / MSVCRT__exit).
Thanks, Piotr
Code taken from onexit logic and adapted-
Signed-off-by: Fabian Maurer dark.shadow4@web.de --- dlls/msvcrt/exit.c | 48 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-)
diff --git a/dlls/msvcrt/exit.c b/dlls/msvcrt/exit.c index 313a06ecd0..070a6753e8 100644 --- a/dlls/msvcrt/exit.c +++ b/dlls/msvcrt/exit.c @@ -30,8 +30,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); #define UNLOCK_EXIT _munlock(_EXIT_LOCK1)
static MSVCRT__onexit_t *MSVCRT_atexit_table = NULL; +static MSVCRT__onexit_t *MSVCRT_atquickexit_table = NULL; static int MSVCRT_atexit_table_size = 0; +static int MSVCRT_atquickexit_table_size = 0; static int MSVCRT_atexit_registered = 0; /* Points to free slot */ +static int MSVCRT_atquickexit_registered = 0; /* Points to free slot */ static MSVCRT_purecall_handler purecall_handler = NULL;
typedef struct MSVCRT__onexit_table_t @@ -78,6 +81,22 @@ static void __MSVCRT__call_atexit(void) } }
+/* INTERNAL: call atexit functions */ +static void __MSVCRT__call_atquickexit(void) +{ + TRACE("%d atquickexit functions to call\n", MSVCRT_atquickexit_registered); + + /* Last registered gets executed first */ + while (MSVCRT_atquickexit_registered > 0) + { + MSVCRT_atquickexit_registered--; + TRACE("next is %p\n",MSVCRT_atquickexit_table[MSVCRT_atquickexit_registered]); + if (MSVCRT_atquickexit_table[MSVCRT_atquickexit_registered]) + (*MSVCRT_atquickexit_table[MSVCRT_atquickexit_registered])(); + TRACE("returned\n"); + } +} + /********************************************************************* * __dllonexit (MSVCRT.@) */ @@ -125,7 +144,8 @@ void CDECL MSVCRT__exit(int exitcode) */ void CDECL MSVCRT_quick_exit(int exitcode) { - FIXME("partial stub: (%d)\n", exitcode); + TRACE("(%d)\n", exitcode); + __MSVCRT__call_atquickexit(); MSVCRT__exit(exitcode); }
@@ -363,7 +383,31 @@ int CDECL MSVCRT_atexit(void (*func)(void)) */ int CDECL MSVCRT__crt_at_quick_exit(void (*func)(void)) { - FIXME("stub: (%p)\n", func); + TRACE("(%p)\n",func); + + if (!func) + return -1; + + LOCK_EXIT; + if (MSVCRT_atquickexit_registered > MSVCRT_atquickexit_table_size - 1) + { + MSVCRT__onexit_t *newtable; + TRACE("expanding table\n"); + newtable = MSVCRT_calloc(MSVCRT_atquickexit_table_size + 32, sizeof(void *)); + if (!newtable) + { + TRACE("failed!\n"); + UNLOCK_EXIT; + return -1; + } + memcpy (newtable, MSVCRT_atquickexit_table, MSVCRT_atquickexit_table_size*sizeof(void *)); + MSVCRT_atquickexit_table_size += 32; + MSVCRT_free (MSVCRT_atquickexit_table); + MSVCRT_atquickexit_table = newtable; + } + MSVCRT_atquickexit_table[MSVCRT_atquickexit_registered] = (MSVCRT__onexit_t)func; + MSVCRT_atquickexit_registered++; + UNLOCK_EXIT; return 0; }
Hi,
On 06/05/18 22:42, Fabian Maurer wrote:
Code taken from onexit logic and adapted-
Why don't you just call onexit functions instead of reimplementing it? Note that you don't need to call MSVCRT__initialize_onexit_table when quick_exit table is declared static.
Thanks, Piotr
Why don't you just call onexit functions instead of reimplementing it? Note that you don't need to call MSVCRT__initialize_onexit_table when quick_exit table is declared static.
What do you mean? AFAIK the onquickexit functions are different functions than the one registered onexit, no? So I need to have a second function that uses a different table. Or put the shared functionality into a shared function.
Regards, Fabian Maurer
On 06/12/18 09:43, Fabian Maurer wrote:
Why don't you just call onexit functions instead of reimplementing it?
Note that you don't need to call MSVCRT__initialize_onexit_table when
quick_exit table is declared static.
What do you mean? AFAIK the onquickexit functions are different functions than the one registered onexit, no? So I need to have a second function that uses a different table. Or put the shared functionality into a shared function.
atexit and at_quick_exit needs to manage similar table of functions. Because of that there's a set of helper functions that can be used to accomplish it (*_onexit_table functions). It's even documented that it's used internally: https://msdn.microsoft.com/en-us/library/mt670601.aspx
Thanks, Piotr
atexit and at_quick_exit needs to manage similar table of functions. Because of that there's a set of helper functions that can be used to accomplish it (*_onexit_table functions). It's even documented that it's used internally: https://msdn.microsoft.com/en-us/library/mt670601.aspx
Yes, this makes sense.
Should I also send in a patch for MSVCRT__onexit to use _register_onexit_function, and for __MSVCRT__call_atexit to use _execute_onexit_table? Because those too duplicate the functionality, that's where I got that from. I'd also add some tests while I'm on it.
Regards, Fabian Maurer
On 06/13/18 08:16, Fabian Maurer wrote:
Should I also send in a patch for MSVCRT__onexit to use _register_onexit_function, and for __MSVCRT__call_atexit to use _execute_onexit_table?
Sure, it makes sense to use this helpers there as well.
Thanks, Piotr
Hi Fabian,
On 06/05/18 22:42, Fabian Maurer wrote:
+/*********************************************************************
_crt_at_quick_exit (UCRTBASE.@)
- */
+int CDECL MSVCRT__crt_at_quick_exit(void (*func)(void)) +{
- FIXME("stub: (%p)\n", func);
- return 0;
+}
The func argument should probably use CDECL calling convention (not that it really matters in case of no-arguments function). Also it's probably better to return -1 (error) in stub.
Thanks, Piotr
Hi Piotr,
The func argument should probably use CDECL calling convention (not that it really matters in case of no-arguments function).
I did it like MSVCRT__crt_atexit did it, first pass the func like this and then cast to MSVCRT__onexit_t. Should I make it MSVCRT__onexit_t right away?
Also it's probably better to return -1 (error) in stub.
Sure can do, although it doesn't matter too much since I later replace it anyways.
Regards, Fabian Maurer
On 06/11/18 23:02, Fabian Maurer wrote:
Hi Piotr,
The func argument should probably use CDECL calling convention (not that
it really matters in case of no-arguments function).
I did it like MSVCRT__crt_atexit did it, first pass the func like this and then cast to MSVCRT__onexit_t. Should I make it MSVCRT__onexit_t right away?
I think it's better to keep function header the same as in native. Could you please also change MSVCRT__crt_atexit header while you're at it?
Thanks, Piotr