Problems on XP

261 views
Skip to first unread message

Robin Dunn

unread,
Dec 31, 2013, 1:30:57 PM12/31/13
to wx-...@googlegroups.com
Hi all,

There are some wxPython users who are having problems with wxPython 3.0
on XP. It is crashing when certain widgets are used, but simple windows
without those widgets work fine. They had no problems like this with
the 2.9.5 release.

I'll try to get an XP VM setup for development again, but in the
meantime one user did this analysis of the msvcr90.dll addresses
reported in the backtrace reported by another user:
https://groups.google.com/d/msg/wxpython-users/5NFI-D6T1aQ/eXug-f1GwfcJ
It seems to indicate that the problem is happening when allocating
memory for TLS?

Does anyone know of any changes between 2.9.5 and 3.0 that could have
caused a problem like this?

--
Robin Dunn
Software Craftsman
http://wxPython.org

Robin Dunn

unread,
Dec 31, 2013, 1:44:35 PM12/31/13
to wx-...@googlegroups.com
I should mention that one of the widgets identified as problematic is
the wxSearchCtrl. Other samples in the wxPython demo have been reported
to be crashing on XP as well, but I don't know yet if they are the same
problem.

Vadim Zeitlin

unread,
Dec 31, 2013, 4:51:53 PM12/31/13
to wx-...@googlegroups.com
On Tue, 31 Dec 2013 10:30:57 -0800 Robin Dunn wrote:

RD> There are some wxPython users who are having problems with wxPython 3.0
RD> on XP. It is crashing when certain widgets are used, but simple windows
RD> without those widgets work fine. They had no problems like this with
RD> the 2.9.5 release.
RD>
RD> I'll try to get an XP VM setup for development again,

This doesn't look like the best way to celebrate New Year :-/ FWIW I have
one (and even a few), but I'm not sure if wxPython uses our DLL binaries,
i.e. if I already have the symbols to debug this or if I need to get them
from somewhere else?

RD> but in the meantime one user did this analysis of the msvcr90.dll
RD> addresses reported in the backtrace reported by another user:
RD> https://groups.google.com/d/msg/wxpython-users/5NFI-D6T1aQ/eXug-f1GwfcJ
RD> It seems to indicate that the problem is happening when allocating
RD> memory for TLS?
RD>
RD> Does anyone know of any changes between 2.9.5 and 3.0 that could have
RD> caused a problem like this?

There have been no changes in this area since 2.9.5 AFAIR and the only
problem with the TLS is http://trac.wxwidgets.org/ticket/13116 which is
perfectly real and serious but which is not new at all.

FWIW I did test some samples under XP, but I don't think I've tested the
search page of the widgets sample (but at least the widgets sample itself
started up fine there AFAIR).

Good luck,
VZ

Dev Player

unread,
Dec 31, 2013, 8:32:13 PM12/31/13
to wx-...@googlegroups.com


# if I run pysliceshell  (which runs PySliceShell.py and uses wx.py.frame.__createmenu() at 
# certain m.Append() statements it will consistantly get the crash mentioned below in __doc__. 
# If you remove certain accelerators in the m.Append() strings, things work.

import sys
import wx

"""
MS-Windows XP Pro SP3 32bit with Python 2.7.5 32 bit
AppName: python.exe     
AppVer: 0.0.0.0     
ModName: wxbase30u_vc90.dll
ModVer: 3.0.0.0     
Offset: 000988e3
"""


class Frame(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        m = wx.Menu()
        ID_MENU1 = wx.NewId()
        m.Append(ID_MENU1, 'Menu1 &1', 'Menu1 tips')

        ID_MENU2 = wx.NewId()
        if 'crash' in sys.argv:
            # \t sometimes causes crash
            # sometimes it is the accelerator

            # I get a crash in wx-3.0-msw\wx\py\frame.py Frame.__createmenus()
            # at m.Append(..., 'Item \t Ctrl+Shift+xxx', lines

            m.Append(ID_MENU2, 'Menu2 \t&2', 'Menu2 tips')
        else:
            m.Append(ID_MENU2, 'Menu2 &2', 'Menu2 tips')

        b = wx.MenuBar()
        b.Append(m, 'Menus')

        self.SetMenuBar(b)


if __name__ == "__main__":
    print('To show crash run python.exe test.py crash')
    
    app = wx.App()
    frame = Frame(None, title='test menu accelerator')
    frame.Show()
    app.MainLoop()


Robin Dunn

unread,
Jan 1, 2014, 7:06:36 PM1/1/14
to wx-...@googlegroups.com
Vadim Zeitlin wrote:
> On Tue, 31 Dec 2013 10:30:57 -0800 Robin Dunn wrote:
>
> RD> There are some wxPython users who are having problems with wxPython 3.0
> RD> on XP. It is crashing when certain widgets are used, but simple windows
> RD> without those widgets work fine. They had no problems like this with
> RD> the 2.9.5 release.
> RD>
> RD> I'll try to get an XP VM setup for development again,
>
> This doesn't look like the best way to celebrate New Year :-/ FWIW I have
> one (and even a few),

I found an old VM I was able to update without too much hassle.

> but I'm not sure if wxPython uses our DLL binaries,
> i.e. if I already have the symbols to debug this or if I need to get them
> from somewhere else?

wxPython includes its own builds of the wx DLLs with some slight
modifications of setup.h, so I don't think it would be compatible with
the stock DLLs.

>
> RD> but in the meantime one user did this analysis of the msvcr90.dll
> RD> addresses reported in the backtrace reported by another user:
> RD> https://groups.google.com/d/msg/wxpython-users/5NFI-D6T1aQ/eXug-f1GwfcJ
> RD> It seems to indicate that the problem is happening when allocating
> RD> memory for TLS?
> RD>
> RD> Does anyone know of any changes between 2.9.5 and 3.0 that could have
> RD> caused a problem like this?
>
> There have been no changes in this area since 2.9.5 AFAIR and the only
> problem with the TLS is http://trac.wxwidgets.org/ticket/13116 which is
> perfectly real and serious but which is not new at all.
>


Here is one of the call stacks at the time of the crash. Setting
wxUSE_COMPILER_TLS to zero appears to have taken care of the problem,
however it is still very puzzling why it worked okay in wxPython 2.9.5
and earlier.


wxbase30ud_vc90.dll!wxThreadSpecificInfo::Get() Line 58 + 0xc bytes C++
wxbase30ud_vc90.dll!wxTranslations::GetUntranslatedString(const
wxString & str={...}) Line 1614 + 0x5 bytes C++
wxmsw30ud_core_vc90.dll!wxGetTranslation(const wxString & str={...},
const wxString & domain={...}) Line 254 + 0xa bytes C++
wxmsw30ud_core_vc90.dll!CompareAccelString(const wxString &
str={...}, const char * accel=0x03191c78) Line 124 + 0xa2 bytes C++
wxmsw30ud_core_vc90.dll!wxAcceleratorEntry::ParseAccel(const wxString
& text={...}, int * flagsOut=0x0021ded8, int * keyOut=0x0021dea8) Line
182 + 0xe bytes C++
wxmsw30ud_core_vc90.dll!wxAcceleratorEntry::Create(const wxString &
str={...}) Line 293 + 0x11 bytes C++
wxmsw30ud_core_vc90.dll!wxMenu::UpdateAccel(wxMenuItem *
item=0x011d8808) Line 374 + 0x2a bytes C++
wxmsw30ud_core_vc90.dll!wxMenu::DoInsertOrAppend(wxMenuItem *
pItem=0x011d8808, unsigned int pos=4294967295) Line 473 C++
wxmsw30ud_core_vc90.dll!wxMenu::DoAppend(wxMenuItem *
item=0x011d8808) Line 772 + 0x1e bytes C++
wxmsw30ud_core_vc90.dll!wxMenuBase::Append(int itemid=5004, const
wxString & text={...}, const wxString & help={...}, wxItemKind
kind=wxITEM_NORMAL) Line 68 C++
_core__d.pyd!_wrap_Menu_Append(_object * __formal=0x00000000, _object
* args=0x010fa860, _object * kwargs=0x0120a818) Line 48034 + 0x19 bytes C++
python27_d.dll!PyCFunction_Call(_object * func=0x01ce29b8, _object *
arg=0x010fa860, _object * kw=0x0120a818) Line 85 + 0xf bytes C
python27_d.dll!ext_do_call(_object * func=0x01ce29b8, _object * * *
pp_stack=0x0021e3a8, int flags=3, int na=0, int nk=0) Line 4333 C
python27_d.dll!PyEval_EvalFrameEx(_frame * f=0x011d72e8, int
throwflag=0) Line 2708 C
python27_d.dll!PyEval_EvalCodeEx(PyCodeObject * co=0x0133e568,
_object * globals=0x011d72e8, _object * locals=0x00000000, _object * *
args=0x011d6fec, int argcount=4, _object * * kws=0x011d6ffc, int
kwcount=0, _object * * defs=0x00000000, int defcount=0, _object *
closure=0x00000000) Line 3253 + 0xb bytes C
python27_d.dll!fast_function(_object * func=0x0133e568, _object * * *
pp_stack=0x0021e554, int n=4, int na=4, int nk=0) Line 4120 + 0x35 bytes C
python27_d.dll!call_function(_object * * * pp_stack=0x0021e554, int
oparg=0) Line 4042 + 0xf bytes C
python27_d.dll!PyEval_EvalFrameEx(_frame * f=0x011d6ea0, int
throwflag=0) Line 2668 C
python27_d.dll!fast_function(_object * func=0x01064e08, _object * * *
pp_stack=0x0021e6ac, int n=1, int na=1, int nk=0) Line 4107 + 0x8 bytes C
python27_d.dll!call_function(_object * * * pp_stack=0x0021e6ac, int
oparg=0) Line 4042 + 0xf bytes C
python27_d.dll!PyEval_EvalFrameEx(_frame * f=0x0112d2f0, int
throwflag=0) Line 2668 C
python27_d.dll!PyEval_EvalCodeEx(PyCodeObject * co=0x010644a8,
_object * globals=0x0112d2f0, _object * locals=0x00000000, _object * *
args=0x011f5f9c, int argcount=7, _object * * kws=0x0120644c, int
kwcount=1, _object * * defs=0x010ce4fc, int defcount=7, _object *
closure=0x00000000) Line 3253 + 0xb bytes C
python27_d.dll!function_call(_object * func=0x010cfb38, _object *
arg=0x011f5f88, _object * kw=0x0120a428) Line 531 + 0x3a bytes C
python27_d.dll!PyObject_Call(_object * func=0x010cfb38, _object *
arg=0x011f5f88, _object * kw=0x0120a428) Line 2529 + 0xf bytes C
python27_d.dll!instancemethod_call(_object * func=0x010cfb38, _object
* arg=0x011f5f88, _object * kw=0x0120a428) Line 2602 + 0x11 bytes C
python27_d.dll!PyObject_Call(_object * func=0x00f0ec38, _object *
arg=0x011f5f88, _object * kw=0x0120a428) Line 2529 + 0xf bytes C
python27_d.dll!do_call(_object * func=0x00f0ec38, _object * * *
pp_stack=0x0021eb1c, int na=7, int nk=1) Line 4239 + 0x8 bytes C
python27_d.dll!call_function(_object * * * pp_stack=0x0021eb1c, int
oparg=1) Line 4044 + 0x7 bytes C
python27_d.dll!PyEval_EvalFrameEx(_frame * f=0x0112dcf8, int
throwflag=0) Line 2668 C
python27_d.dll!PyEval_EvalCodeEx(PyCodeObject * co=0x00f6f928,
_object * globals=0x0112dcf8, _object * locals=0x00000000, _object * *
args=0x0120719c, int argcount=1, _object * * kws=0x00a87754, int
kwcount=2, _object * * defs=0x019e711c, int defcount=13, _object *
closure=0x00000000) Line 3253 + 0xb bytes C
python27_d.dll!function_call(_object * func=0x010f22f8, _object *
arg=0x01207188, _object * kw=0x0120a2d8) Line 531 + 0x3a bytes C
python27_d.dll!PyObject_Call(_object * func=0x010f22f8, _object *
arg=0x01207188, _object * kw=0x0120a2d8) Line 2529 + 0xf bytes C
python27_d.dll!instancemethod_call(_object * func=0x010f22f8, _object
* arg=0x01207188, _object * kw=0x0120a2d8) Line 2602 + 0x11 bytes C
python27_d.dll!PyObject_Call(_object * func=0x00f0ebf8, _object *
arg=0x00a31038, _object * kw=0x0120a2d8) Line 2529 + 0xf bytes C
python27_d.dll!slot_tp_init(_object * self=0x012071c0, _object *
args=0x00a31038, _object * kwds=0x0120a2d8) Line 5692 + 0x11 bytes C
python27_d.dll!type_call(_typeobject * type=0x00f9c470, _object *
args=0x00a31038, _object * kwds=0x0120a2d8) Line 745 + 0x35 bytes C
python27_d.dll!PyObject_Call(_object * func=0x00f9c470, _object *
arg=0x00a31038, _object * kw=0x0120a2d8) Line 2529 + 0xf bytes C
python27_d.dll!do_call(_object * func=0x00f9c470, _object * * *
pp_stack=0x0021efe4, int na=0, int nk=2) Line 4239 + 0x8 bytes C
python27_d.dll!call_function(_object * * * pp_stack=0x0021efe4, int
oparg=2) Line 4044 + 0x7 bytes C
python27_d.dll!PyEval_EvalFrameEx(_frame * f=0x0112bda8, int
throwflag=0) Line 2668 C
python27_d.dll!PyEval_EvalCodeEx(PyCodeObject * co=0x010f4988,
_object * globals=0x0112bda8, _object * locals=0x00000000, _object * *
args=0x012070f4, int argcount=1, _object * * kws=0x00000000, int
kwcount=0, _object * * defs=0x00000000, int defcount=0, _object *
closure=0x00000000) Line 3253 + 0xb bytes C
python27_d.dll!function_call(_object * func=0x01205090, _object *
arg=0x012070e0, _object * kw=0x00000000) Line 531 + 0x3a bytes C
python27_d.dll!PyObject_Call(_object * func=0x01205090, _object *
arg=0x012070e0, _object * kw=0x00000000) Line 2529 + 0xf bytes C
python27_d.dll!instancemethod_call(_object * func=0x01205090, _object
* arg=0x012070e0, _object * kw=0x00000000) Line 2602 + 0x11 bytes C
python27_d.dll!PyObject_Call(_object * func=0x00f0edb8, _object *
arg=0x00a31038, _object * kw=0x00000000) Line 2529 + 0xf bytes C
python27_d.dll!PyEval_CallObjectWithKeywords(_object *
func=0x00f0edb8, _object * arg=0x00a31038, _object * kw=0x00000000)
Line 3891 C
_core__d.pyd!wxPyApp::_BootstrapApp() Line 635 + 0x10 bytes C++
_core__d.pyd!_wrap_PyApp__BootstrapApp(_object * __formal=0x00000000,
_object * args=0x011fff50) Line 35293 C++
python27_d.dll!PyCFunction_Call(_object * func=0x01ce65b8, _object *
arg=0x01207038, _object * kw=0x01202578) Line 101 + 0xe bytes C
python27_d.dll!ext_do_call(_object * func=0x01ce65b8, _object * * *
pp_stack=0x0021f4f4, int flags=3, int na=0, int nk=0) Line 4333 C
python27_d.dll!PyEval_EvalFrameEx(_frame * f=0x0106fad8, int
throwflag=0) Line 2708 C
python27_d.dll!PyEval_EvalCodeEx(PyCodeObject * co=0x012fa2c8,
_object * globals=0x0106fad8, _object * locals=0x00000000, _object * *
args=0x011e8934, int argcount=1, _object * * kws=0x011e8938, int
kwcount=0, _object * * defs=0x00000000, int defcount=0, _object *
closure=0x00000000) Line 3253 + 0xb bytes C
python27_d.dll!fast_function(_object * func=0x012fa2c8, _object * * *
pp_stack=0x0021f6a0, int n=1, int na=1, int nk=0) Line 4120 + 0x35 bytes C
python27_d.dll!call_function(_object * * * pp_stack=0x0021f6a0, int
oparg=0) Line 4042 + 0xf bytes C
python27_d.dll!PyEval_EvalFrameEx(_frame * f=0x011e87d8, int
throwflag=0) Line 2668 C
python27_d.dll!PyEval_EvalCodeEx(PyCodeObject * co=0x012ff208,
_object * globals=0x011e87d8, _object * locals=0x00000000, _object * *
args=0x0110764c, int argcount=2, _object * * kws=0x00000000, int
kwcount=0, _object * * defs=0x01c7f244, int defcount=4, _object *
closure=0x00000000) Line 3253 + 0xb bytes C
python27_d.dll!function_call(_object * func=0x01c78560, _object *
arg=0x01107638, _object * kw=0x00000000) Line 531 + 0x3a bytes C
python27_d.dll!PyObject_Call(_object * func=0x01c78560, _object *
arg=0x01107638, _object * kw=0x00000000) Line 2529 + 0xf bytes C
python27_d.dll!instancemethod_call(_object * func=0x01c78560, _object
* arg=0x01107638, _object * kw=0x00000000) Line 2602 + 0x11 bytes C
python27_d.dll!PyObject_Call(_object * func=0x00f0eaf8, _object *
arg=0x011fff18, _object * kw=0x00000000) Line 2529 + 0xf bytes C
python27_d.dll!slot_tp_init(_object * self=0x011fff50, _object *
args=0x011fff18, _object * kwds=0x00000000) Line 5692 + 0x11 bytes C
python27_d.dll!type_call(_typeobject * type=0x010c8420, _object *
args=0x011fff18, _object * kwds=0x00000000) Line 745 + 0x35 bytes C
python27_d.dll!PyObject_Call(_object * func=0x010c8420, _object *
arg=0x011fff18, _object * kw=0x00000000) Line 2529 + 0xf bytes C
python27_d.dll!do_call(_object * func=0x010c8420, _object * * *
pp_stack=0x0021fb68, int na=1, int nk=0) Line 4239 + 0x8 bytes C
python27_d.dll!call_function(_object * * * pp_stack=0x0021fb68, int
oparg=0) Line 4044 + 0x7 bytes C
python27_d.dll!PyEval_EvalFrameEx(_frame * f=0x01229da8, int
throwflag=0) Line 2668 C
python27_d.dll!fast_function(_object * func=0x011fdf88, _object * * *
pp_stack=0x0021fcc0, int n=0, int na=0, int nk=0) Line 4107 + 0x8 bytes C
python27_d.dll!call_function(_object * * * pp_stack=0x0021fcc0, int
oparg=0) Line 4042 + 0xf bytes C
python27_d.dll!PyEval_EvalFrameEx(_frame * f=0x00adfd78, int
throwflag=0) Line 2668 C
python27_d.dll!PyEval_EvalCodeEx(PyCodeObject * co=0x00a6bec8,
_object * globals=0x00adfd78, _object * locals=0x00a836c8, _object * *
args=0x00000000, int argcount=0, _object * * kws=0x00000000, int
kwcount=0, _object * * defs=0x00000000, int defcount=0, _object *
closure=0x00000000) Line 3253 + 0xb bytes C
python27_d.dll!PyEval_EvalCode(PyCodeObject * co=0x00a6bec8, _object
* globals=0x00a836c8, _object * locals=0x00a836c8) Line 672 + 0x1f bytes C
python27_d.dll!run_mod(_mod * mod=0x00c0d178, const char *
filename=0x00985c83, _object * globals=0x00a836c8, _object *
locals=0x00a836c8, PyCompilerFlags * flags=0x0021ff30, _arena *
arena=0x00b2e0c0) Line 1370 + 0x11 bytes C
python27_d.dll!PyRun_FileExFlags(_iobuf * fp=0x10311448, const char *
filename=0x00985c83, int start=257, _object * globals=0x00a836c8,
_object * locals=0x00a836c8, int closeit=1, PyCompilerFlags *
flags=0x0021ff30) Line 1356 + 0x1d bytes C
python27_d.dll!PyRun_SimpleFileExFlags(_iobuf * fp=0x10311448, const
char * filename=0x00985c83, int closeit=1, PyCompilerFlags *
flags=0x0021ff30) Line 949 + 0x22 bytes C
python27_d.dll!PyRun_AnyFileExFlags(_iobuf * fp=0x10311448, const
char * filename=0x00985c83, int closeit=1, PyCompilerFlags *
flags=0x0021ff30) Line 752 + 0x15 bytes C
python27_d.dll!Py_Main(int argc=2, char * * argv=0x00985c58) Line
643 + 0x39 bytes C
python_d.exe!main(int argc=2, char * * argv=0x00985c58) Line 23 +
0xe bytes C
python_d.exe!__tmainCRTStartup() Line 586 + 0x19 bytes C
python_d.exe!mainCRTStartup() Line 403 C
kernel32.dll!7c817077()
[Frames below may be incorrect and/or missing, no symbols loaded
for kernel32.dll]

Vadim Zeitlin

unread,
Jan 2, 2014, 2:33:38 PM1/2/14
to wx-...@googlegroups.com
On Wed, 01 Jan 2014 16:06:36 -0800 Robin Dunn wrote:

RD> wxPython includes its own builds of the wx DLLs with some slight
RD> modifications of setup.h, so I don't think it would be compatible with
RD> the stock DLLs.

What exactly prevents wxPython from using the stock DLLs? It would be
really nice if we could reuse them for both C++ and Python.

RD> Here is one of the call stacks at the time of the crash. Setting
RD> wxUSE_COMPILER_TLS to zero appears to have taken care of the problem,
RD> however it is still very puzzling why it worked okay in wxPython 2.9.5
RD> and earlier.

I don't know neither but then the error is affected by some semi-random
factors, as explained in the article linked to from the bug, so it's not
completely unexpected.

But this shows once again that we really must do something about this,
people keep getting bitten by this. So should we disable compiler TLS under
Windows unconditionally even in spite of the performance cost? Or do it
only in the DLL build and at least make the problem more rare by limiting
it only to the people linking in static wx libraries into their own DLLs?

What do people think?
VZ

Dev Player

unread,
Jan 2, 2014, 3:14:09 PM1/2/14
to wx-...@googlegroups.com
As I have as of yet to make any project using Python a high performance one so therefore I choose stability over performance. Also consider help keeping the auto-build process easy to maintain, change, and document-able.

wsu

unread,
Jan 2, 2014, 7:16:13 PM1/2/14
to wx-...@googlegroups.com
But if Python is to use the stock DLLs, I don't want my C++ programs to be suffering performance penalties.  (I personally am using static linking, so I think this problem would not actually hit me, but I definitely don't want the precedent of the Python tail wagging the C++ dog.)

Stefa...@t-online.de

unread,
Jan 3, 2014, 4:55:05 AM1/3/14
to wx-...@googlegroups.com
Hi,

VZ> But this shows once again that we really must do something about this,
VZ> people keep getting bitten by this. So should we disable compiler TLS under
VZ> Windows unconditionally even in spite of the performance cost?
(snipp)
VZ> What do people think?

Two years ago (and maybe even one year ago) I would have said that
stability wins over performance, especially for a GUI library and with
such a "semi-random" bug which practically guarantees that it will
show up in the worst possible moment.
But with XP being out-of-support within the next few weeks, I really don't
think it's worth the trouble to do anything about it any more ...

Regards,
Stefan




Eric Jensen

unread,
Jan 3, 2014, 5:13:22 AM1/3/14
to Vadim Zeitlin
Hello Vadim,

Thursday, January 2, 2014, 8:33:38 PM, you wrote:

VZ> But this shows once again that we really must do something about this,
VZ> people keep getting bitten by this. So should we disable compiler TLS under
VZ> Windows unconditionally even in spite of the performance cost?

What magnitude of performance cost are we even talking about? If it's
just a few % i'd tend to choose the "safe mode" by default and
developers can change their wxUSE_COMPILER_TLS to 1 if they want.

Eric


Pete Bannister

unread,
Jan 3, 2014, 5:28:10 AM1/3/14
to wx-...@googlegroups.com
Perhaps you could put in an assert/throw if the code is running from a
DLL and was compiled with wxUSE_COMPILER_TLS != 0?

You could put in a startup check for this with GetModuleHandle(NULL) and
then use GetModuleFilename and then mmap the file and take a look at the
PE data to see if it has IMAGE_FILE_DLL:
http://stackoverflow.com/questions/6309179/how-to-tell-if-a-file-is-an-exe-or-a-dll.

Maybe offer a way of not compiling in the check too just in case it
causes problems.


Pete

Vadim Zeitlin

unread,
Jan 3, 2014, 10:27:23 AM1/3/14
to wx-...@googlegroups.com
On Fri, 03 Jan 2014 10:55:05 +0100 Stefa...@t-online.de wrote:

So> Two years ago (and maybe even one year ago) I would have said that
So> stability wins over performance, especially for a GUI library and with
So> such a "semi-random" bug which practically guarantees that it will
So> show up in the worst possible moment.
So> But with XP being out-of-support within the next few weeks, I really don't
So> think it's worth the trouble to do anything about it any more ...

I'm very tempted to agree with this, but the trouble is that whatever is
the official state of XP support, we still do support it and I don't see us
dropping support for it any time soon (i.e. not in 3.2.0). According to the
last statistics I saw, XP still accounts for 30% of the web users, so I
don't think it's going to just disappear completely in a few weeks or
months.

On Fri, 03 Jan 2014 10:28:10 +0000 Pete Bannister wrote:

PB> Perhaps you could put in an assert/throw if the code is running from a
PB> DLL and was compiled with wxUSE_COMPILER_TLS != 0?

Notice that we need to do this only if the DLL is dynamically loaded, i.e.
using LoadLibrary() and not implicitly by the loader during the program
startup. And I don't know how to distinguish between the two cases.

PB> You could put in a startup check for this with GetModuleHandle(NULL) and
PB> then use GetModuleFilename and then mmap the file and take a look at the
PB> PE data to see if it has IMAGE_FILE_DLL:
PB> http://stackoverflow.com/questions/6309179/how-to-tell-if-a-file-is-an-exe-or-a-dll.

This could help with the problem of checking whether our code is inside
the DLL or not (because it could be in a DLL even if it wasn't compiled as
a DLL itself) though, so this is helpful, thanks!

EJ> VZ> But this shows once again that we really must do something about this,
EJ> VZ> people keep getting bitten by this. So should we disable compiler TLS under
EJ> VZ> Windows unconditionally even in spite of the performance cost?
EJ>
EJ> What magnitude of performance cost are we even talking about? If it's
EJ> just a few % i'd tend to choose the "safe mode" by default and
EJ> developers can change their wxUSE_COMPILER_TLS to 1 if they want.

You can run the benchmarks to check for yourself but the difference is
much more significant than a few %, it's rather a few times:

% ./vc120_mswu/bench.exe /a 100 {wx,Win32,Compiler,Dummy}TLS
wxWidgets benchmarking program
Build: 3.1.0 (wchar_t,Visual C++ 1800,wx containers,compatible with 2.8)
Benchmarking wxTLS: 942ms total, 9.41 avg (min=6, max=14)
Benchmarking Win32TLS: 4771ms total, 47.69 avg (min=47, max=50)
Benchmarking CompilerTLS: 621ms total, 6.20 avg (min=6, max=7)
Benchmarking DummyTLS: 601ms total, 6.00 avg (min=6, max=7)

As you can see, compiler TLS has almost no overhead at all compared to
direct variable access benchmarked by DummyTLS (I wonder by what kind of
magic is this achieved) while our code overhead manages to slow it down by
50% (which is pretty bad and should be checked too). But directly using
Win32 API (without any wx overhead) is 8 times slower.

But I think we probably still need to disable the use of compiler TLS,
being slow is bad but mysteriously crashing is worse. The only case in
which we can certainly leave it enabled would be when using a compiler not
targeting XP anyhow, i.e. the compiler from the default toolset of VC11 and
later. Does anybody know how can we distinguish between "vc110" and
"vc110_xp" toolsets at compilation time?

Thanks,
VZ

David Connet

unread,
Jan 3, 2014, 10:47:47 AM1/3/14
to wx-...@googlegroups.com
On 1/3/2014 7:27 AM, Vadim Zeitlin wrote:
> But I think we probably still need to disable the use of compiler TLS,
> being slow is bad but mysteriously crashing is worse. The only case in
> which we can certainly leave it enabled would be when using a compiler not
> targeting XP anyhow, i.e. the compiler from the default toolset of VC11 and
> later. Does anybody know how can we distinguish between "vc110" and
> "vc110_xp" toolsets at compilation time?
>
> Thanks,
> VZ
>

What about keying on the WINVER definition?
#if defined(WINVER) && WINVER >= 0x600
-> targeting vista+
...

Vadim Zeitlin

unread,
Jan 3, 2014, 10:55:48 AM1/3/14
to wx-...@googlegroups.com
On Fri, 03 Jan 2014 07:47:47 -0800 David Connet wrote:

DC> On 1/3/2014 7:27 AM, Vadim Zeitlin wrote:
DC> > But I think we probably still need to disable the use of compiler TLS,
DC> > being slow is bad but mysteriously crashing is worse. The only case in
DC> > which we can certainly leave it enabled would be when using a compiler not
DC> > targeting XP anyhow, i.e. the compiler from the default toolset of VC11 and
DC> > later. Does anybody know how can we distinguish between "vc110" and
DC> > "vc110_xp" toolsets at compilation time?
DC>
DC> What about keying on the WINVER definition?
DC> #if defined(WINVER) && WINVER >= 0x600
DC> -> targeting vista+

Is WINVER really predefined by the compiler? I think it comes from the
project files only and so won't depend on the toolset being used.

Regards,
VZ

David Connet

unread,
Jan 3, 2014, 12:14:27 PM1/3/14
to wx-...@googlegroups.com
> From: Vadim Zeitlin <va...@wxwidgets.org>

>To: wx-...@googlegroups.com
>Sent: Friday, January 3, 2014 7:55 AM
>Subject: Re[2]: [wx-dev] Problems on XP


The user is supposed to define it to indicate the minimum OS supported (well, target API that is linked against). If someone is using vc110_xp, they shouldn't have WINVER set to 0x600 or they may link against some APIs that don't exist on their target system! (If not set, AFAIK the compiler selects the highest platform it knows about)

This is generally the very first thing I do in my stdafx.h file - before _any_ header is included.


Dave

Eric Jensen

unread,
Jan 3, 2014, 12:24:32 PM1/3/14
to David Connet
Hello David,

Friday, January 3, 2014, 6:14:27 PM, you wrote:

>> From: Vadim Zeitlin <va...@wxwidgets.org>

>>To: wx-...@googlegroups.com
>>Sent: Friday, January 3, 2014 7:55 AM
>>Subject: Re[2]: [wx-dev] Problems on XP
>>
>>
>>On Fri, 03 Jan 2014 07:47:47 -0800 David Connet wrote:
>>
>>DC> On 1/3/2014 7:27 AM, Vadim Zeitlin wrote:
>>DC> >���But I think we probably still need to disable the use of compiler TLS,
>>DC> > being slow is bad but mysteriously crashing is worse. The only case in
>>DC> > which we can certainly leave it enabled would be when using a compiler not
>>DC> > targeting XP anyhow, i.e. the compiler from the default toolset of VC11 and
>>DC> > later. Does anybody know how can we distinguish between "vc110" and
>>DC> > "vc110_xp" toolsets at compilation time?
>>DC>
>>DC> What about keying on the WINVER definition?
>>DC> #if defined(WINVER) && WINVER >= 0x600
>>DC> -> targeting vista+
>>
>>Is WINVER really predefined by the compiler? I think it comes from the
>>project files only and so won't depend on the toolset being used.


DC> The user is supposed to define it to indicate the minimum OS
DC> supported (well, target API that is linked against). If someone is
DC> using vc110_xp, they shouldn't have WINVER set to 0x600 or they
DC> may link against some APIs that don't exist on their target
DC> system! (If not set, AFAIK the compiler selects the highest
DC> platform it knows about)

No. I target XP, but i still have WINVER set to 0x601, because i want
to use Vista+ features and i check for the OS at runtime.

Eric


Pete Bannister

unread,
Jan 3, 2014, 12:30:25 PM1/3/14
to wx-...@googlegroups.com
> As you can see, compiler TLS has almost no overhead at all compared to
> direct variable access benchmarked by DummyTLS (I wonder by what kind of
> magic is this achieved) while our code overhead manages to slow it down by
> 50% (which is pretty bad and should be checked too). But directly using
> Win32 API (without any wx overhead) is 8 times slower.
I think this is because the compiler can directly access the TEB (thread
execution block) through the gs segment register with a loader-fixed-up
tls index, which is only a few asm instructions.
Quite an interesting read:
http://www.nynaeve.net/?p=185

Using the win32 functions has the overhead of function calls and
presumably some additional list/array manipulation, whereas directly
using the TIB can be done inline with very little overhead. I expect
that there is a single global tls variable that is used to get at a
secondary tls table in the win32 case. Maybe not though.

If you have a dllmain function then you can apparently check to see if
it is being loaded statically or dynamically using lpReserved which is
non-null for static loads (see msdn docs for dllmain,
DLL_PROCESS_ATTACH):
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx
<http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583%28v=vs.85%29.aspx>

Presumably this is not an option if the static lib version of wx was
linked into a dll though. In which case there are presumably other
problems - such as when do you call TlsAlloc?

Pete

Robin Dunn

unread,
Jan 3, 2014, 1:08:00 PM1/3/14
to wx-...@googlegroups.com
Vadim Zeitlin wrote:
> On Wed, 01 Jan 2014 16:06:36 -0800 Robin Dunn wrote:
>
> RD> wxPython includes its own builds of the wx DLLs with some slight
> RD> modifications of setup.h, so I don't think it would be compatible with
> RD> the stock DLLs.
>
> What exactly prevents wxPython from using the stock DLLs? It would be
> really nice if we could reuse them for both C++ and Python.

Probably mostly because I haven't tried it yet ;-) and since I would
like to put most of my available time into the new Phoenix project I'm
trying to keep changes in Classic wxPython to a minimum.


> On Fri, 03 Jan 2014 10:28:10 +0000 Pete Bannister wrote:
>
> PB> Perhaps you could put in an assert/throw if the code is running from a
> PB> DLL and was compiled with wxUSE_COMPILER_TLS != 0?
>
> Notice that we need to do this only if the DLL is dynamically loaded, i.e.
> using LoadLibrary() and not implicitly by the loader during the program
> startup. And I don't know how to distinguish between the two cases.

Or, as in the case of wxPython, implicitly loaded by a DLL that is
dynamically loaded with LoadLibrary. So that will probably complicate
the detection even more.

Bryan Petty

unread,
Jan 3, 2014, 4:14:50 PM1/3/14
to wxWidgets Development
On Fri, Jan 3, 2014 at 2:55 AM, Stefa...@t-online.de
<Stefa...@t-online.de> wrote:
> But with XP being out-of-support within the next few weeks, I really don't
> think it's worth the trouble to do anything about it any more ...

I think this way too for the most part, but it's also worth noting
that regardless of what MS is doing, Net Applications market share
reports still claim that about 31% of all desktop computers are
running XP, of course, with the qualifier that this is based on
internet site traffic analytics, and may be different for desktop
application share, if not just different with the wx user base.

What version of wx are we talking about anyway though? If it's 3.0.1,
then it might still be worth considering, but if we're talking about
3.2+, then probably not.

--
Regards,
Bryan Petty

Vadim Zeitlin

unread,
Jan 3, 2014, 7:26:06 PM1/3/14
to wx-...@googlegroups.com
On Fri, 3 Jan 2014 18:24:32 +0100 Eric Jensen wrote:

EJ> >>Is WINVER really predefined by the compiler? I think it comes from the
EJ> >>project files only and so won't depend on the toolset being used.
EJ>
EJ> DC> The user is supposed to define it to indicate the minimum OS
EJ> DC> supported (well, target API that is linked against). If someone is
EJ> DC> using vc110_xp, they shouldn't have WINVER set to 0x600 or they
EJ> DC> may link against some APIs that don't exist on their target
EJ> DC> system! (If not set, AFAIK the compiler selects the highest
EJ> DC> platform it knows about)
EJ>
EJ> No. I target XP, but i still have WINVER set to 0x601, because i want
EJ> to use Vista+ features and i check for the OS at runtime.

And so does wx, so it had never been necessary to predefine WINVER with wx
applications (and, in fact, counter productive, as it would just lock you
out of using any new features even if they're available).

We really need some way to distinguish between the compilers used by vc1x0
and vc1x0_xp toolsets...

Regards,
VZ

Vadim Zeitlin

unread,
Jan 3, 2014, 7:35:55 PM1/3/14
to wx-...@googlegroups.com
On Fri, 03 Jan 2014 17:30:25 +0000 Pete Bannister wrote:

PB> > As you can see, compiler TLS has almost no overhead at all compared to
PB> > direct variable access benchmarked by DummyTLS (I wonder by what kind of
PB> > magic is this achieved) while our code overhead manages to slow it down by
PB> > 50% (which is pretty bad and should be checked too). But directly using
PB> > Win32 API (without any wx overhead) is 8 times slower.
PB> I think this is because the compiler can directly access the TEB (thread
PB> execution block) through the gs segment register with a loader-fixed-up
PB> tls index, which is only a few asm instructions.
PB> Quite an interesting read:
PB> http://www.nynaeve.net/?p=185

Yes, this is exactly the blog linked from the bug. And it's true that I
shouldn't be surprised by the little overhead of using compiler TLS
(although it's still an extra indirection compared to a normal variable).
Nor is the overhead of using Win32 TLS functions really unexpected. But the
50% lost in wx wrappers is still a nasty surprise.

PB> If you have a dllmain function then you can apparently check to see if
PB> it is being loaded statically or dynamically using lpReserved which is
PB> non-null for static loads (see msdn docs for dllmain,
PB> DLL_PROCESS_ATTACH):
PB> http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx
PB> <http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583%28v=vs.85%29.aspx>

How interesting, I didn't know about it, thanks!

PB> Presumably this is not an option if the static lib version of wx was
PB> linked into a dll though.

Yes, unfortunately this still doesn't solve this problem.

PB> In which case there are presumably other problems - such as when do you
PB> call TlsAlloc?

I don't see what the problem is exactly here, but maybe I'm missing
something.

Anyhow, more I think about this, more I become convinced that the only
solution we have is to never use compiler TLS if we can be ran under XP
(i.e. unless we're being compiled with a compiler that can't target XP at
all). Because even if we do find a way to detect the potentially
problematic situation, what are we going to do? The best we can hope for is
to give a warning and then what is the programmer supposed to do? He still
needs to rebuild wx without wxUSE_COMPILER_TLS. Which means that he can't
use our official binaries at all anyhow, which is probably not something we
want to encourage...

The absolutely ideal solution would be to select between the TLS
implementation to use during run-time but this would require:

1. Detecting when the compiler TLS can't be used, which we still can't do
reliably.

2. Virtualizing everything which is not completely trivial to do and will
make thread-specific variables access even slower.

Regards,
VZ

David Connet

unread,
Jan 3, 2014, 7:37:59 PM1/3/14
to wx-...@googlegroups.com
> From: Vadim Zeitlin <va...@wxwidgets.org>

> To: wx-...@googlegroups.com
> Cc:
> Sent: Friday, January 3, 2014 4:26 PM
> Subject: Re[5]: [wx-dev] Problems on XP
Ah, found it.
#ifdef _USING_V110_SDK71_

I verified that change the project settings to v110_xp did set that. Got the clue from http://blogs.msdn.com/b/vcblog/archive/2012/10/08/windows-xp-targeting-with-c-in-visual-studio-2012.aspx

This is why I'm staying on vc10 for as long as I support xp... since I build wx from the command line.

Dave

Vadim Zeitlin

unread,
Jan 3, 2014, 7:48:34 PM1/3/14
to wx-...@googlegroups.com
On Fri, 3 Jan 2014 16:37:59 -0800 (PST) David Connet wrote:

DC> Ah, found it.
DC> #ifdef _USING_V110_SDK71_

Great, thanks! The interesting thing is that it seems that the same symbol
(and *not* _USING_V120_SDK71_ as I'd expect) is also used with VC12 (VS2013).

DC> I verified that change the project settings to v110_xp did set that.
DC> Got the clue from
DC> http://blogs.msdn.com/b/vcblog/archive/2012/10/08/windows-xp-targeting-with-c-in-visual-studio-2012.aspx
DC>
DC> This is why I'm staying on vc10 for as long as I support xp... since I
DC> build wx from the command line.

Yes, specifying the toolset to use from the command line is not very
convenient. Or at least I didn't find any way to do it conveniently yet...

Regards,
VZ

David Connet

unread,
Jan 3, 2014, 8:10:25 PM1/3/14
to wx-...@googlegroups.com
----- Original Message -----

> From: Vadim Zeitlin <va...@wxwidgets.org>
> To: wx-...@googlegroups.com
> Cc:
> Sent: Friday, January 3, 2014 4:48 PM
> Subject: Re[7]: [wx-dev] Problems on XP
>
> On Fri, 3 Jan 2014 16:37:59 -0800 (PST) David Connet wrote:
>
> DC> Ah, found it.
> DC> #ifdef _USING_V110_SDK71_
>
> Great, thanks! The interesting thing is that it seems that the same symbol
> (and *not* _USING_V120_SDK71_ as I'd expect) is also used with VC12
> (VS2013).

Backwards compatibility? (Out of curiosity, I just fired up my vc12 and saw the same)

If I remember right, I think sdk7.1 is essentially vc10. (and the max sdk that can be used for xp) Vc11 added support for the older sdk via the v110_xp target, hence the name. And why the name didn't change. And vc12 confused it by added the v120_xp target (which means sdk7.1 with vc12). The define probably shouldn't have been named with 'V110' in it, but such is life...
(random musings that may or may not reflect reality since I didn't verify anything - except that _USING_V110_SDK71_ is set in v120_xp)

Dave

Reply all
Reply to author
Forward
0 new messages