From: "Vladimir Šironja" <vladimir.sironja@gmail.com>
To: 74311@debbugs.gnu.org
Subject: bug#74311: Long startup time on windows (with simple fix)
Date: Mon, 11 Nov 2024 12:30:54 +0100 [thread overview]
Message-ID: <CAOUA3jmqao0iGaZLO850FUe0xeKHjPfO7Nr6CBdqTMAy8S3-_w@mail.gmail.com> (raw)
Hello,
I have (*had!) a very annoying occurrence of long startup times on
windows 10 & 11.
Ended up with emacs 29.4 but tried several 28 and 26 versions with no
difference.
It takes sometimes around 30 secs for emacs to come up.
But not always, let's say a third of strarts were normal within a second.
Tried excluding relevant directories from virus check; no difference.
Also tried starting without init files (-Q); no difference.
So compiled with debug symbols gcc version 14.2.0 on msys2.
(Had to set manually add "#define HAVE_SYS_WAIT_H 1" into src/config.h
- but that's another issue, already handled several times in this
group.)
In gdb-debugger caught the hanging operation:
Thread 1 (Thread 19568.0x24c0):
#0 0x00007ff9e2331244 in ntdll!ZwAlpcSendWaitReceivePort () from
C:\WINDOWS\SYSTEM32\ntdll.dll
#1 0x00007ff9e0a4b032 in RpcBindingFromStringBindingW () from
C:\WINDOWS\System32\rpcrt4.dll
#2 0x00007ff9e0a47efb in RpcBindingFromStringBindingW () from
C:\WINDOWS\System32\rpcrt4.dll
#3 0x00007ff9e0a66c19 in RPCRT4!I_RpcSendReceive () from
C:\WINDOWS\System32\rpcrt4.dll
#4 0x00007ff9e0a66b5f in RPCRT4!NdrSendReceive () from
C:\WINDOWS\System32\rpcrt4.dll
#5 0x00007ff9e0af07da in RPCRT4!NdrClientCall3 () from
C:\WINDOWS\System32\rpcrt4.dll
#6 0x00007ff9e0aef69b in RPCRT4!NdrClientCall3 () from
C:\WINDOWS\System32\rpcrt4.dll
#7 0x00007ff9e11c6046 in SECHOST!LookupAccountSidLocalW () from
C:\WINDOWS\System32\sechost.dll
#8 0x00007ff9e11c5d4f in SECHOST!LookupAccountSidLocalW () from
C:\WINDOWS\System32\sechost.dll
#9 0x00007ff9e11dead3 in SECHOST!LookupAccountSidLocalA () from
C:\WINDOWS\System32\sechost.dll
#10 0x00007ff9e0d9bce0 in LookupAccountSidA () from
C:\WINDOWS\System32\advapi32.dll
#11 0x00007ff63569a990 in lookup_account_sid (lpSystemName=0x0,
Sid=0x4b414a8, Name=0xbfe740 "\030D╦5\001", cbName=0xbfe320,
DomainName=0x0, cbDomainName=0xbfe328, peUse=0xbfe314) at w32.c:706
#12 0x00007ff63569d35f in init_user_info () at w32.c:2319
#13 0x00007ff63569f151 in init_environment (argv=0xd315b0) at w32.c:3198
#14 0x00007ff6354b93de in main (argc=1, argv=0xd315b0) at emacs.c:2120
Ok, so noticed that it if s_pfn_Lookup_Account_Sid (LookupAccountSid)
invoked for the *second* time, it blocks for around half a minute
causing the delay.
However, when lucky, the function is invoked only once and it just
works as always.
I didn't analyse the cause for multiple invocations, but added a
simple naive workaround to test the theory - which simply caches the
results of LookupAccountSid.
from w32.c:
struct lookup_account_sid_cache {
BOOL ret;
LPTSTR Name;
LPSTR DomainName;
SID_NAME_USE peUse;
};
static BOOL WINAPI
lookup_account_sid (LPCTSTR lpSystemName,
PSID Sid,
LPTSTR Name,
LPDWORD cbName,
LPTSTR DomainName,
LPDWORD cbDomainName,
PSID_NAME_USE peUse)
{
static struct lookup_account_sid_cache cache = { 0, NULL, NULL, 0 };
static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
return FALSE;
}
if (g_b_init_lookup_account_sid == 0)
{
g_b_init_lookup_account_sid = 1;
hm_advapi32 = LoadLibrary ("Advapi32.dll");
s_pfn_Lookup_Account_Sid = (LookupAccountSid_Proc)
get_proc_addr (hm_advapi32, LookupAccountSid_Name);
}
if (s_pfn_Lookup_Account_Sid == NULL)
{
return FALSE;
}
BOOL ret;
if(!cache.ret) {
ret = s_pfn_Lookup_Account_Sid (
lpSystemName,
Sid,
Name,
cbName,
DomainName,
cbDomainName,
peUse);
if(ret) {
cache.ret = ret;
cache.Name = Name && *Name ? strdup(Name) : NULL;
cache.DomainName = DomainName && *DomainName ? strdup(DomainName) : NULL;
cache.peUse = peUse ? *peUse : 0;
}
}
else {
ret = cache.ret;
if(cache.Name) {
strncpy(Name, cache.Name, *cbName);
*cbName = strlen(cache.Name);
}
if(cache.DomainName && cbDomainName && *cbDomainName > 0) {
if(DomainName) strncpy(DomainName, cache.DomainName, *cbDomainName);
*cbDomainName = strlen(cache.DomainName);
}
if(peUse) *peUse = cache.peUse;
}
return ret;
}
Tried about 30 times since the fix: works like a charm.
Please change the code - to invoke the offending winapi function only
once, since it obviously punishes the second caller. Or perhaps a
caching mechanism as above.
Cheers to fellow emacsers!
And thx for all the good work form the team
Bye
Vlado
next reply other threads:[~2024-11-11 11:30 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-11 11:30 Vladimir Šironja [this message]
2024-11-11 13:13 ` bug#74311: Long startup time on windows (with simple fix) Eli Zaretskii
2024-11-11 14:12 ` Vladimir Šironja
2024-11-11 14:46 ` Eli Zaretskii
2024-11-11 15:18 ` Ship Mints
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAOUA3jmqao0iGaZLO850FUe0xeKHjPfO7Nr6CBdqTMAy8S3-_w@mail.gmail.com \
--to=vladimir.sironja@gmail.com \
--cc=74311@debbugs.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).