x64 hg.exe

Adrian Buehlmann adrian at cadifra.com
Fri Jun 22 12:26:44 CDT 2012


On 2012-06-22 16:38, Adrian Buehlmann wrote:
> On 2012-06-22 13:07, Adrian Buehlmann wrote:
>> On 2012-06-22 03:42, Adrian Buehlmann wrote:
>>> I've built an exemaker exe
>>>
>>>   hg-x64-385eaa517487.exe
>>
>> No luck. The serve tests fail with the exe when -d is specified:
>>
>>   $ hg --traceback serve -n test -p 20059 -d --pid-file=hg.pid -E errors.log
>>   Traceback (most recent call last):
>>     File "C:\Users\adi\hgrepos\hg-main\mercurial\dispatch.py", line 88, in _runcatch
>>       return _dispatch(req)
>>     File "C:\Users\adi\hgrepos\hg-main\mercurial\dispatch.py", line 739, in _dispatch
>>       cmdpats, cmdoptions)
>>     File "C:\Users\adi\hgrepos\hg-main\mercurial\dispatch.py", line 513, in runcommand
>>       ret = _runcommand(ui, options, cmd, d)
>>     File "C:\Users\adi\hgrepos\hg-main\mercurial\dispatch.py", line 829, in _runcommand
>>       return checkargs()
>>     File "C:\Users\adi\hgrepos\hg-main\mercurial\dispatch.py", line 800, in checkargs
>>       return cmdfunc()
>>     File "C:\Users\adi\hgrepos\hg-main\mercurial\dispatch.py", line 736, in <lambda>
>>       d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
>>     File "C:\Users\adi\hgrepos\hg-main\mercurial\util.py", line 475, in check
>>       return func(*args, **kwargs)
>>     File "C:\Users\adi\hgrepos\hg-main\mercurial\extensions.py", line 139, in wrap
>>       util.checksignature(origfn), *args, **kwargs)
>>     File "C:\Users\adi\hgrepos\hg-main\mercurial\util.py", line 475, in check
>>       return func(*args, **kwargs)
>>     File "C:\Users\adi\hgrepos\hg-main\hgext\mq.py", line 3505, in mqcommand
>>       return orig(ui, repo, *args, **kwargs)
>>     File "C:\Users\adi\hgrepos\hg-main\mercurial\util.py", line 475, in check
>>       return func(*args, **kwargs)
>>     File "C:\Users\adi\hgrepos\hg-main\mercurial\commands.py", line 5120, in serve
>>       cmdutil.service(opts, initfn=service.init, runfn=service.run)
>>     File "C:\Users\adi\hgrepos\hg-main\mercurial\cmdutil.py", line 486, in service
>>       raise util.Abort(_('child process failed to start'))
>>   Abort: child process failed to start
>>   abort: child process failed to start
>>
>> And it's not because of a problem with the port. An identical
>>
>>   $ python hg.py --traceback serve -n test -p 20070 -d --pid-file=hg.pid -E errors.log
>>
>>   adi at kork /hgrepos/hg-main
>>
>> works.
>>
>> Without -d, the exe works:
>>
>>   $ hg --traceback serve -n test -p 20059
>>
>> So there's a problem with --daemon in combination with the exe.
> 
> With
> 
> diff --git a/mercurial/util.py b/mercurial/util.py
> --- a/mercurial/util.py
> +++ b/mercurial/util.py
> @@ -1395,6 +1395,7 @@
>      if SIGCHLD is not None:
>          prevhandler = signal.signal(SIGCHLD, handler)
>      try:
> +        print "calling spawndetached():", args
>          pid = spawndetached(args)
>          while not condfn():
>              if ((pid in terminated or not testpid(pid))
> 
> and hg.exe, I see (in sh of MSYS):
> 
> $ hg --traceback serve -n test -p 20070 -d --pid-file=hg.pid -E errors.log
> calling spawndetached(): ['C:\\Users\\adi\\hgrepos\\hg-main\\hg.exe', 'C:\\Users\\adi\\hgrepos\\hg-main\\hg.py', '--traceback', 'serve', '-n', 'test', '-p', '20070', '-d', '--pid-file=hg.pid', '-E', 'errors.log', '--daemon-pipefds=c:\\tmp\\hg-service-za7au5']
> 
> If I use the hg file (with Python in PATH), I see:
> 
> $ hg --traceback serve -n test -p 20070 -d --pid-file=hg.pid -E errors.log
> calling spawndetached(): ['c:\\Python\\python.exe', './hg', '--traceback', 'serve', '-n', 'test', '-p', '20070', '-d', '--pid-file=hg.pid', '-E', 'errors.log', '--daemon-pipefds=c:\\tmp\\hg-service-r3tnre']
> 
> Similar to:
> 
> $ python hg.py --traceback serve -n test -p 20070 -d --pid-file=hg.pid -E errors.log
> calling spawndetached(): ['c:\\Python\\python.exe', 'hg.py', '--traceback', 'serve', '-n', 'test', '-p', '20070', '-d', '--pid-file=hg.pid', '-E', 'errors.log', '--daemon-pipefds=c:\\tmp\\hg-service-x8rclt']
> 
> 
> So, for the hg.exe case, we have something unusual: The first arg is not the python interpreter, but the hg.exe. The second arg is the hg.py python script. But running 'hg.exe hg.py' obviously doesn't work:
> 
>   $ hg.exe hg.py version
>   hg: unknown command 'hg.py'


I did some wild experimental exemaker hacking (yikes!).

I simulated a frozen exe:

diff --git a/exemaker.c b/exemaker.c
--- a/exemaker.c
+++ b/exemaker.c
@@ -120,7 +120,9 @@
 const char bang_python[] = "#!python.exe";
 const char lib_os_py[] = "\\lib\\os.py";
 const char cannot_find_dll_in[] = "Cannot find DLL in ";
+const char Py_Initialize_str[] = "Py_Initialize";
 const char Py_Main_str[] = "Py_Main";
+const char PyRun_SimpleString_str[] = "PyRun_SimpleString";
 
 int __cdecl
 main(int ac, char **av)
@@ -128,8 +130,10 @@
     HINSTANCE mainDll;
     DWORD n;
     char* argv[100];
+    void (__cdecl * Py_Initialize)();
     int (__cdecl * Py_Main)(int argc, char *argv[]);
     void (__cdecl * Py_SetPythonHome)(char* home);
+    int (__cdecl * PyRun_SimpleString)(const char* command);
     char fullfile[512];
     char workingdir[512];
     char requestedapplication[256];
@@ -239,12 +243,27 @@
     }
 
     /* get entry points */
+
+    Py_Initialize = (void*) GetProcAddress(mainDll, Py_Initialize_str);
+    if (!Py_Initialize) {
+        strncpy_s(message, sizeof message, cannot_find, sizeof cannot_find);
+        strcat_s(message, sizeof message, Py_Initialize_str);
+        goto error;
+    }
+
     Py_Main = (void*) GetProcAddress(mainDll, Py_Main_str);
     if (!Py_Main) {
         strncpy_s(message, sizeof message, cannot_find, sizeof cannot_find);
         strcat_s(message, sizeof message, Py_Main_str);
         goto error;
     }
+    
+    PyRun_SimpleString = (void*) GetProcAddress(mainDll, PyRun_SimpleString_str);
+    if (!PyRun_SimpleString) {
+        strncpy_s(message, sizeof message, cannot_find, sizeof cannot_find);
+        strcat_s(message, sizeof message, PyRun_SimpleString_str);
+        goto error;
+    }
 
     /* get paths */
     GetModuleFileName(mainDll, exefile, sizeof(exefile));
@@ -279,6 +298,9 @@
     SetEnvironmentVariable("PYTHONPATH", NULL);
     SetEnvironmentVariable("PYTHONVERBOSE", NULL);
 
+    Py_Initialize();
+    PyRun_SimpleString("import sys; sys.frozen=True\n");
+
     argv[0] = exefile;
     argv[1] = "-S"; /* don't import site just yet */
     argv[2] = scriptfile;



This fixes the "hg serve -d" call itself, but causes some other collateral damage,
presumably due to the fact that it's a lie elsewhere that we are frozen.

It seems that the templater notices the lie:

+  $ cat errors.log
+  127.0.0.1 - - [22/Jun/2012 17:21:02] Exception happened during processing request '/file':
+  Traceback (most recent call last):
+    File "C:\Users\adi\hgrepos\hg-main\mercurial\hgweb\server.py", line 77, in do_POST
+      self.do_write()
+    File "C:\Users\adi\hgrepos\hg-main\mercurial\hgweb\server.py", line 70, in do_write
+      self.do_hgweb()
+    File "C:\Users\adi\hgrepos\hg-main\mercurial\hgweb\server.py", line 137, in do_hgweb
+      for chunk in self.server.application(env, self._start_response):
+    File "C:\Users\adi\hgrepos\hg-main\mercurial\hgweb\hgweb_mod.py", line 92, in __call__
+      return self.run_wsgi(req)
+    File "C:\Users\adi\hgrepos\hg-main\mercurial\hgweb\hgweb_mod.py", line 181, in run_wsgi
+      tmpl = self.templater(req)
+    File "C:\Users\adi\hgrepos\hg-main\mercurial\hgweb\hgweb_mod.py", line 264, in templater
+      style, mapfile = templater.stylemap(styles, self.templatepath)
+    File "C:\Users\adi\hgrepos\hg-main\mercurial\templater.py", line 392, in stylemap
+      raise RuntimeError("No hgweb templates found in %r" % paths)
+  RuntimeError: No hgweb templates found in []


More information about the Mercurial-devel mailing list