From 6453a55538a3e3af1fbf3ae0b905988967a2200a Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 20 Oct 2020 10:10:34 +0000 Subject: Proposed fix for [c2483bfe4b]: tk fontchooser on macOS can automatically open on startup, can lead to crashes. Which also works for Tcl 8.7 and 9.0 --- generic/tkPlatDecls.h | 5 +++++ macosx/tkMacOSXInit.c | 45 +++++++++++++++++++++++++++------------------ unix/tkAppInit.c | 8 ++++++++ 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/generic/tkPlatDecls.h b/generic/tkPlatDecls.h index bad633f..2fea41e 100644 --- a/generic/tkPlatDecls.h +++ b/generic/tkPlatDecls.h @@ -193,6 +193,11 @@ extern const TkPlatStubs *tkPlatStubsPtr; /* !END!: Do not edit above this line. */ +#if !defined(USE_SYSTEM_EXIT) && defined(MAC_OSX_TK) +EXTERN int TkMacOSXIsLaunched(void); +EXTERN TCL_NORETURN void TkMacOSXExitProc(void *); +#endif + #ifdef __cplusplus } #endif diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index 0e7dfe4..1323333 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -294,26 +294,33 @@ static void closePanels( * correctly for all termination scenarios. */ +#if !defined(USE_SYSTEM_EXIT) +static Bool doCleanupFromExit = NO; + +int TkMacOSXIsLaunched(void) { + return doCleanupFromExit == YES; +} + TCL_NORETURN void TkMacOSXExitProc( - ClientData clientdata) + void *clientdata) { - closePanels(); - - /* - * Make sure we don't get called again. This can happen, e.g. with - * fossil diff -tk. - */ - - Tcl_SetExitProc(NULL); + Bool doCleanup = doCleanupFromExit; + if (doCleanupFromExit) { + doCleanupFromExit = NO; /* prevent possible recursive call. */ + closePanels(); + } /* * Tcl_Exit does not call Tcl_Finalize if there is an exit proc installed. */ Tcl_Finalize(); - [(TKApplication *)NSApp superTerminate:nil]; /* Should not return. */ + if (doCleanup == YES) { + [(TKApplication *)NSApp superTerminate:nil]; /* Should not return. */ + } exit((int)clientdata); /* Convince the compiler that we don't return. */ } +#endif /* * This signal handler is installed for the SIGINT, SIGHUP and SIGTERM signals @@ -326,6 +333,8 @@ TCL_NORETURN void TkMacOSXExitProc( */ static void TkMacOSXSignalHandler(int signal) { + (void)signal; + Tcl_Exit(1); } @@ -343,7 +352,6 @@ TkpInit( if (!initialized) { struct stat st; Bool shouldOpenConsole = NO; - Bool isLaunched = NO; Bool stdinIsNullish = (!isatty(0) && (fstat(0, &st) || (S_ISCHR(st.st_mode) && st.st_blocks == 0))); @@ -443,7 +451,9 @@ TkpInit( Tcl_SetVar2(interp, "tcl_interactive", NULL, "1", TCL_GLOBAL_ONLY); } - isLaunched = YES; +#if !defined(USE_SYSTEM_EXIT) + doCleanupFromExit = YES; +#endif shouldOpenConsole = YES; } if (shouldOpenConsole) { @@ -466,7 +476,9 @@ TkpInit( FILE *null = fopen("/dev/null", "w"); dup2(fileno(null), STDOUT_FILENO); dup2(fileno(null), STDERR_FILENO); - isLaunched = YES; +#if !defined(USE_SYSTEM_EXIT) + doCleanupFromExit = YES; +#endif } /* @@ -513,11 +525,8 @@ TkpInit( # if !defined(USE_SYSTEM_EXIT) - if (isLaunched || (isatty(0) && isatty(1))) { - Tcl_ExitProc *prevExitProc = Tcl_SetExitProc(TkMacOSXExitProc); - if (prevExitProc) { - Tcl_SetExitProc((TCL_NORETURN Tcl_ExitProc *)prevExitProc); - } + if ((isatty(0) && isatty(1))) { + doCleanupFromExit = YES; } # endif diff --git a/unix/tkAppInit.c b/unix/tkAppInit.c index 13bcdde..aa9315c 100644 --- a/unix/tkAppInit.c +++ b/unix/tkAppInit.c @@ -15,6 +15,9 @@ #undef BUILD_tk #undef STATIC_BUILD #include "tk.h" +#if !defined(USE_SYSTEM_EXIT) && defined(MAC_OSX_TK) +# include "tkMacOSX.h" +#endif #ifdef TK_TEST extern Tcl_PackageInitProc Tktest_Init; @@ -110,6 +113,11 @@ Tcl_AppInit( return TCL_ERROR; } Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); +#if !defined(USE_SYSTEM_EXIT) && defined(MAC_OSX_TK) + if (TkMacOSXIsLaunched()) { + Tcl_SetExitProc(TkMacOSXExitProc); + } +#endif #ifdef TK_TEST if (Tktest_Init(interp) == TCL_ERROR) { -- cgit v0.12 From 4c940e28df4d5740b0ab2904ed4c673e5678ddf0 Mon Sep 17 00:00:00 2001 From: marc_culler Date: Tue, 20 Oct 2020 17:41:43 +0000 Subject: Avoid platform-specific conditional compilation where possible. --- generic/tkPlatDecls.h | 5 ----- macosx/tkMacOSXInit.c | 19 +++++++++++-------- macosx/tkMacOSXPort.h | 8 ++++++++ unix/tkAppInit.c | 12 ++++++------ 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/generic/tkPlatDecls.h b/generic/tkPlatDecls.h index 2fea41e..bad633f 100644 --- a/generic/tkPlatDecls.h +++ b/generic/tkPlatDecls.h @@ -193,11 +193,6 @@ extern const TkPlatStubs *tkPlatStubsPtr; /* !END!: Do not edit above this line. */ -#if !defined(USE_SYSTEM_EXIT) && defined(MAC_OSX_TK) -EXTERN int TkMacOSXIsLaunched(void); -EXTERN TCL_NORETURN void TkMacOSXExitProc(void *); -#endif - #ifdef __cplusplus } #endif diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index 1323333..5103a84 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -113,6 +113,7 @@ static int TkMacOSXGetAppPathCmd(ClientData cd, Tcl_Interp *ip, /* * Initialize event processing. */ + TkMacOSXInitAppleEvents(_eventInterp); /* @@ -294,14 +295,14 @@ static void closePanels( * correctly for all termination scenarios. */ -#if !defined(USE_SYSTEM_EXIT) +#if defined(USE_CUSTOM_EXIT_PROC) static Bool doCleanupFromExit = NO; -int TkMacOSXIsLaunched(void) { +int TkpWantsExitProc(void) { return doCleanupFromExit == YES; } -TCL_NORETURN void TkMacOSXExitProc( +TCL_NORETURN void TkpExitProc( void *clientdata) { Bool doCleanup = doCleanupFromExit; @@ -318,7 +319,7 @@ TCL_NORETURN void TkMacOSXExitProc( if (doCleanup == YES) { [(TKApplication *)NSApp superTerminate:nil]; /* Should not return. */ } - exit((int)clientdata); /* Convince the compiler that we don't return. */ + exit((long)clientdata); /* Convince the compiler that we don't return. */ } #endif @@ -451,9 +452,11 @@ TkpInit( Tcl_SetVar2(interp, "tcl_interactive", NULL, "1", TCL_GLOBAL_ONLY); } -#if !defined(USE_SYSTEM_EXIT) + +#if defined(USE_CUSTOM_EXIT_PROC) doCleanupFromExit = YES; #endif + shouldOpenConsole = YES; } if (shouldOpenConsole) { @@ -476,7 +479,7 @@ TkpInit( FILE *null = fopen("/dev/null", "w"); dup2(fileno(null), STDOUT_FILENO); dup2(fileno(null), STDERR_FILENO); -#if !defined(USE_SYSTEM_EXIT) +#if defined(USE_CUSTOM_EXIT_PROC) doCleanupFromExit = YES; #endif } @@ -520,10 +523,10 @@ TkpInit( * calling [NSApplication terminate]. This does not work correctly if * the process is part of an exec pipeline, so it is only used if the * process was launched by the launcher or if both stdin and stdout are - * ttys. If an exit proc was already installed we leave it in place. + * ttys. */ -# if !defined(USE_SYSTEM_EXIT) +# if defined(USE_CUSTOM_EXIT_PROC) if ((isatty(0) && isatty(1))) { doCleanupFromExit = YES; diff --git a/macosx/tkMacOSXPort.h b/macosx/tkMacOSXPort.h index 76dd974..461204e 100644 --- a/macosx/tkMacOSXPort.h +++ b/macosx/tkMacOSXPort.h @@ -185,4 +185,12 @@ MODULE_SCOPE void TkMacOSXHandleMapOrUnmap(Tk_Window tkwin, XEvent *event); #define TkpHandleMapOrUnmap(tkwin, event) TkMacOSXHandleMapOrUnmap(tkwin, event) +/* + * Used by tkAppInit + */ + +#define USE_CUSTOM_EXIT_PROC +EXTERN int TkpWantsExitProc(void); +EXTERN TCL_NORETURN void TkpExitProc(void *); + #endif /* _TKMACPORT */ diff --git a/unix/tkAppInit.c b/unix/tkAppInit.c index aa9315c..ecd9dfe 100644 --- a/unix/tkAppInit.c +++ b/unix/tkAppInit.c @@ -15,9 +15,7 @@ #undef BUILD_tk #undef STATIC_BUILD #include "tk.h" -#if !defined(USE_SYSTEM_EXIT) && defined(MAC_OSX_TK) -# include "tkMacOSX.h" -#endif +#include "tkPort.h" #ifdef TK_TEST extern Tcl_PackageInitProc Tktest_Init; @@ -113,9 +111,11 @@ Tcl_AppInit( return TCL_ERROR; } Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); -#if !defined(USE_SYSTEM_EXIT) && defined(MAC_OSX_TK) - if (TkMacOSXIsLaunched()) { - Tcl_SetExitProc(TkMacOSXExitProc); + +#if defined(USE_CUSTOM_EXIT_PROC) + if (TkpWantsExitProc()) { + /* The cast below avoids warnings from old gcc compilers. */ + Tcl_SetExitProc((void *)TkpExitProc); } #endif -- cgit v0.12 From 9c472e72196238d8550cab9eeeb10bf9ed74be31 Mon Sep 17 00:00:00 2001 From: marc_culler Date: Tue, 20 Oct 2020 20:15:00 +0000 Subject: Make Tcl_Finalize run when a launched app is terminated with command-Q --- macosx/tkMacOSXHLEvents.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/macosx/tkMacOSXHLEvents.c b/macosx/tkMacOSXHLEvents.c index 615653d..5055f38 100644 --- a/macosx/tkMacOSXHLEvents.c +++ b/macosx/tkMacOSXHLEvents.c @@ -570,13 +570,18 @@ TkMacOSXDoHLEvent( static int ReallyKillMe( Tcl_Event *eventPtr, - int flags) + TCL_UNUSED(int)) { Tcl_Interp *interp = ((KillEvent *) eventPtr)->interp; int quit = Tcl_FindCommand(interp, "::tk::mac::Quit", NULL, 0)!=NULL; - int code = Tcl_EvalEx(interp, quit ? "::tk::mac::Quit" : "exit", -1, TCL_EVAL_GLOBAL); + if (!quit) { + Tcl_Exit(0); + } + + int code = Tcl_EvalEx(interp, "::tk::mac::Quit", -1, TCL_EVAL_GLOBAL); if (code != TCL_OK) { + /* * Should be never reached... */ -- cgit v0.12