/pypy/module/_cffi_backend/errorbox.py
https://github.com/mozillazg/pypy · Python · 115 lines · 98 code · 16 blank · 1 comment · 5 complexity · b96d4580c6f11489e9190cf37f30864d MD5 · raw file
- # for Windows only
- import sys
- from rpython.rlib import jit
- from rpython.rtyper.lltypesystem import lltype, rffi
- from rpython.translator.tool.cbuild import ExternalCompilationInfo
- MESSAGEBOX = sys.platform == "win32"
- MODULE = r"""
- #include <Windows.h>
- #pragma comment(lib, "user32.lib")
- static void *volatile _cffi_bootstrap_text;
- RPY_EXTERN int _cffi_errorbox1(void)
- {
- return InterlockedCompareExchangePointer(&_cffi_bootstrap_text,
- (void *)1, NULL) == NULL;
- }
- static DWORD WINAPI _cffi_bootstrap_dialog(LPVOID ignored)
- {
- Sleep(666); /* may be interrupted if the whole process is closing */
- MessageBoxA(NULL, (char *)_cffi_bootstrap_text,
- "PyPy: Python-CFFI error",
- MB_OK | MB_ICONERROR);
- _cffi_bootstrap_text = NULL;
- return 0;
- }
- RPY_EXTERN void _cffi_errorbox(char *text)
- {
- /* Show a dialog box, but in a background thread, and
- never show multiple dialog boxes at once. */
- HANDLE h;
- _cffi_bootstrap_text = text;
- h = CreateThread(NULL, 0, _cffi_bootstrap_dialog,
- NULL, 0, NULL);
- if (h != NULL)
- CloseHandle(h);
- }
- """
- if MESSAGEBOX:
- eci = ExternalCompilationInfo(
- separate_module_sources=[MODULE],
- post_include_bits=["RPY_EXTERN int _cffi_errorbox1(void);\n"
- "RPY_EXTERN void _cffi_errorbox(char *);\n"])
- cffi_errorbox1 = rffi.llexternal("_cffi_errorbox1", [],
- rffi.INT, compilation_info=eci)
- cffi_errorbox = rffi.llexternal("_cffi_errorbox", [rffi.CCHARP],
- lltype.Void, compilation_info=eci)
- class Message:
- def __init__(self, space):
- self.space = space
- self.text_p = lltype.nullptr(rffi.CCHARP.TO)
- def start_error_capture(self):
- ok = cffi_errorbox1()
- if rffi.cast(lltype.Signed, ok) != 1:
- return None
- return self.space.appexec([], """():
- import sys
- class FileLike:
- def write(self, x):
- try:
- of.write(x)
- except:
- pass
- self.buf += x
- fl = FileLike()
- fl.buf = ''
- of = sys.stderr
- sys.stderr = fl
- def done():
- sys.stderr = of
- return fl.buf
- return done
- """)
- def stop_error_capture(self, w_done):
- if w_done is None:
- return
- w_text = self.space.call_function(w_done)
- p = rffi.str2charp(self.space.bytes_w(w_text),
- track_allocation=False)
- if self.text_p:
- rffi.free_charp(self.text_p, track_allocation=False)
- self.text_p = p # keepalive
- cffi_errorbox(p)
- @jit.dont_look_inside
- def start_error_capture(space):
- msg = space.fromcache(Message)
- return msg.start_error_capture()
- @jit.dont_look_inside
- def stop_error_capture(space, x):
- msg = space.fromcache(Message)
- msg.stop_error_capture(x)
- else:
- def start_error_capture(space):
- return None
- def stop_error_capture(space, nothing):
- pass