From 08bf7cb962704437b0b19ac106e2792ace395a46 Mon Sep 17 00:00:00 2001 From: Stefan Schippers Date: Mon, 31 Aug 2020 13:54:37 +0200 Subject: [PATCH] defer tk windows/menu/widgets creation and Xevent binding setup after xinit.c completes X initialization. This avoids theoretical race condidions if a ConfigureNotify or Expose event is delivered before all Xlib initialization completed. --- src/xinit.c | 19 +++++++- src/xschem.tcl | 119 +++++++++++++++++++++++++++++-------------------- 2 files changed, 87 insertions(+), 51 deletions(-) diff --git a/src/xinit.c b/src/xinit.c index fd126a8b..3d4f00e9 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -1340,6 +1340,13 @@ int Tcl_AppInit(Tcl_Interp *inter) init_done=1; /* 20171008 moved before option processing, otherwise xwin_exit will not be invoked */ /* leaving undo buffer and other garbage around. */ + + /* */ + /* Completing tk windows creation (see xschem.tcl, build_windows) and event binding */ + /* *AFTER* X initialization done */ + /* */ + tcleval("build_windows"); + /* */ /* START PROCESSING USER OPTIONS */ /* */ @@ -1403,11 +1410,18 @@ int Tcl_AppInit(Tcl_Interp *inter) } if(do_print) { if(!filename) { - fprintf(errfp, "xschem: can't do a print without a filename\n"); + dbg(0, "xschem: can't do a print without a filename\n"); tcleval( "exit"); } if(do_print==1) ps_draw(); - else if(do_print == 2) { tcleval("tkwait visibility .drw"); print_image(); } + else if(do_print == 2) { + if(!has_x) { + dbg(0, "xschem: can not do a png export if no X11 present / Xserver running (check if DISPLAY set).\n"); + } else { + tcleval("tkwait visibility .drw"); + print_image(); + } + } else svg_draw(); } @@ -1439,6 +1453,7 @@ int Tcl_AppInit(Tcl_Interp *inter) /* END PROCESSING USER OPTIONS */ /* */ + if(!no_readline) { tcleval( "if {![catch {package require tclreadline}]} " "{::tclreadline::readline customcompleter completer; ::tclreadline::Loop }" ) ; diff --git a/src/xschem.tcl b/src/xschem.tcl index 51a8ecce..c8b3bf0c 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -2870,6 +2870,70 @@ proc toolbar_hide {} { set $toolbar_visible 0 } + +## this function sets up all tk windows and binds X events. It is executed by xinit.c after completing +## all X initialization. This avoids race conditions. +## In previous flow xschem.tcl was setting up windows and events before X initialization was completed by xinit.c. +## this could lead to crashes on some (may be slow) systems due to Configure/Expose events being delivered +## before xschem being ready to handle them. +proc build_windows {} { + global env + if { ( $::OS== "Windows" || [string length [lindex [array get env DISPLAY] 1] ] > 0 ) + && ![info exists no_x]} { + pack .statusbar.2 -side left + pack .statusbar.3 -side left + pack .statusbar.4 -side left + pack .statusbar.5 -side left + pack .statusbar.6 -side left + pack .statusbar.7 -side left + pack .statusbar.1 -side left -fill x + pack .drw -anchor n -side top -fill both -expand true + pack .menubar -anchor n -side top -fill x -before .drw + toolbar_show + pack .statusbar -after .drw -anchor sw -fill x + bind .statusbar.5 { xschem set cadgrid $grid; focus .drw} + bind .statusbar.3 { xschem set cadsnap $snap; focus .drw} + ### + ### Tk event handling + ### + ### bind .drv {xschem callback