From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: yue wang Newsgroups: gmane.emacs.devel Subject: I broke through the limitation of only 32 child processes that can be created on windows emacs Date: Sun, 16 Jun 2024 17:09:45 +0800 Message-ID: Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="0000000000004ea112061afe367d" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="13919"; mail-complaints-to="usenet@ciao.gmane.io" To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Jun 16 14:22:26 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1sIott-0003MF-PY for ged-emacs-devel@m.gmane-mx.org; Sun, 16 Jun 2024 14:22:26 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sIotj-0001GP-Fu; Sun, 16 Jun 2024 08:22:15 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sIlth-0001yk-LF for emacs-devel@gnu.org; Sun, 16 Jun 2024 05:10:01 -0400 Original-Received: from mail-lf1-x133.google.com ([2a00:1450:4864:20::133]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sIlte-0006zX-7M for emacs-devel@gnu.org; Sun, 16 Jun 2024 05:10:01 -0400 Original-Received: by mail-lf1-x133.google.com with SMTP id 2adb3069b0e04-52c94cf4c9bso4146822e87.2 for ; Sun, 16 Jun 2024 02:09:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1718528996; x=1719133796; darn=gnu.org; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=7TtaA4Bb7/TYc3F2SM8I+6MzIbXpotVv8edZDfEe6rM=; b=fYPMOocF1g818FISeBzNbym+AgjeMpKleJSbobDzyikVYFM8wuWtWmo408PxNVl/7X Wmhb3pL3gHAyAcfn8Rz2hyhqV9IjOfi03rk3ZHuDmz6GYoTjgyXXkxGQ/8C15hpd2G2F YfxaR31GCseYHzBcZh+mDL1iQk35KItvdmeQOMbnhpdFIMdJvrJlS8m8U6p74txO7nun 5swi8qI/4D7/VNV0jamgKPSuYbXjsMoKXNQgPh4aEtugkl97YnnnAW+9+n+1fmTo49hj jrzSDwv2uBIMqyrcf7OoOji/q+/yLP3xmuZL83X0GTCSmgViqBL01jwVB2lcacG9Xxr/ wjyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718528996; x=1719133796; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=7TtaA4Bb7/TYc3F2SM8I+6MzIbXpotVv8edZDfEe6rM=; b=Ye47/dl7aguUXgpFEu09Vg6KscJfOlGRKbHkJhHgjfl+4ihOij+qy50NxRDrYtbxoj n6JOzDCgsWQh6UOh/ZNSETrxXTVe7ludauR6bWy6I5aVEYcEqk0p+SdoAb8VqlaOFV4j 9h6CCG9q0vMk6V5mvicIvHbcaB2lFP+lJ9soYutR/+ohr/cP1KWvr/MEOvjJQKtx+obV Gp8gFC4RxbwErxi8d966M3nk/On4t+Y954HlevR2+qV0pBo2D57A3hjLD7dir0t5gg/i T+lmXcYtQf5ANtofAdPn4AITDalnqx+lKREbDKhkyXs5aSx1AdWAbSy9Ioli3KgdQQcS ipfA== X-Gm-Message-State: AOJu0Yys+X9Bo51E7GBV2wdKLj7tOOglOmxxAKdai/+8lKscCLpk/j5q sbUm+yLlQYl6PwUDgnOc06+s8MmeKQrOznQGlO+eKMapYOj3ittKLFAtI95EM7v1typ6XzZj6zo jugiQ7R2Td9vjopY/AVrEjAAlLx5kw/UodZI= X-Google-Smtp-Source: AGHT+IHtLFXFkoqzo5a9F9osE20Vif8TxpaqO00euD/pwr1PlgJKCUovRu/3LPMTGwoaIPh8d2bajZCsuI7grtwUCVo= X-Received: by 2002:a05:6512:32b2:b0:52c:890e:bf23 with SMTP id 2adb3069b0e04-52ca6e65850mr5812504e87.21.1718528995399; Sun, 16 Jun 2024 02:09:55 -0700 (PDT) Received-SPF: pass client-ip=2a00:1450:4864:20::133; envelope-from=nihaoaheheda@gmail.com; helo=mail-lf1-x133.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sun, 16 Jun 2024 08:22:14 -0400 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:320192 Archived-At: --0000000000004ea112061afe367d Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable the related discusstion is here https://emacs-china.org/t/windows-emacs-2024-6-16/27392 I modified from github commit 08e38818f6ff4e514ac291bc5a7686f4390759b0 . 1 in build phase add macro -DFD_SETSIZE=3D4096 2 modify w32.h and w32pro.h git diff is below diff --git a/src/w32.h b/src/w32.h index cf470ae9901..0340f10e62b 100644 --- a/src/w32.h +++ b/src/w32.h @@ -29,7 +29,7 @@ along with GNU Emacs. If not, see < https://www.gnu.org/licenses/>. */ /* File descriptor set emulation. */ /* MSVC runtime library has limit of 64 descriptors by default */ -#define FD_SETSIZE 64 +#define FD_SETSIZE 4096 typedef struct { unsigned int bits[FD_SETSIZE / 32]; } fd_set; diff --git a/src/w32proc.c b/src/w32proc.c index 40181e09830..60918cb4a41 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -62,6 +62,215 @@ along with GNU Emacs. If not, see < https://www.gnu.org/licenses/>. */ #include "syssignal.h" #include "w32term.h" #include "coding.h" +#include + +#define MY_MAXIMUM_WAIT_OBJECTS 4096 +// =E6=9C=80=E5=A4=A7=E7=AD=89=E5=BE=85=E5=AF=B9=E8=B1=A1=E6=95=B0=EF=BC= =8C=E9=A2=9D=E5=A4=96=E7=9A=84=E4=B8=80=E4=B8=AA=E7=94=A8=E4=BA=8E=E7=BA=BF= =E7=A8=8B=E9=80=80=E5=87=BAevent +#define MY_MAX_WAIT_OBJECTS 63 +#define MY_WAIT_TIMEOUT 0x9999 +#define MY_WAIT_FAILED 0x9998 +#define MY_WAIT_ABANDONED_0 0x5000 + + +// =E7=BA=BF=E7=A8=8B=E5=8F=82=E6=95=B0=E7=BB=93=E6=9E=84 +typedef struct { + HANDLE *handles; + int count; + BOOL bWaitAll; + DWORD dwMilliseconds; + HANDLE completionEvent; // =E7=94=A8=E4=BA=8E=E9=80=9A=E7=9F=A5=E4=B8= =BB=E7=BA=BF=E7=A8=8B=E8=AF=A5=E7=BA=BF=E7=A8=8B=E7=9A=84WaitForMultipleObj= ects=E5=B7=B2=E5=AE=8C=E6=88=90 + DWORD *threadResult; // =E8=8E=B7=E5=8F=96=E7=BA=BF=E7=A8=8B=E8=B0=83= =E7=94=A8WaitForMultipleObjects=E7=9A=84=E8=BF=94=E5=9B=9E=E5=80=BC + HANDLE exitEvent; // =E7=94=A8=E4=BA=8E=E6=8E=A7=E5=88=B6=E7=BA=BF=E7= =A8=8B=E9=80=80=E5=87=BA +} WaitForThreadData; + +// =E7=BA=BF=E7=A8=8B=E5=87=BD=E6=95=B0=EF=BC=8C=E7=AD=89=E5=BE=85=E4=B8= =80=E7=BB=84=E5=8F=A5=E6=9F=84 +DWORD WINAPI WaitForThreadProc(LPVOID lpParam) { + WaitForThreadData *params =3D (WaitForThreadData *)lpParam; + HANDLE *allHandles =3D (HANDLE *)malloc((params->count + 1) * sizeof(HANDLE)); + memcpy(allHandles, params->handles, params->count * sizeof(HANDLE)); + allHandles[params->count] =3D params->exitEvent; + + DWORD result =3D WaitForMultipleObjects(params->count + 1, allHandles, params->bWaitAll, params->dwMilliseconds); + if (result =3D=3D WAIT_OBJECT_0 + params->count) { + // exitEvent =E8=A2=AB=E8=A7=A6=E5=8F=91=EF=BC=8C=E7=BA=BF=E7=A8= =8B=E9=80=80=E5=87=BA + result =3D WAIT_TIMEOUT; + } else { + *params->threadResult =3D result; + } + + // =E9=80=9A=E7=9F=A5=E4=B8=BB=E7=BA=BF=E7=A8=8B=E8=AF=A5=E7=BB=84=E5= =B7=B2=E5=AE=8C=E6=88=90 + SetEvent(params->completionEvent); + free(allHandles); + return result; +} +// =E6=89=A9=E5=B1=95=E7=9A=84 WaitForMultipleObjects =E5=87=BD=E6=95=B0 = =EF=BC=8C=E6=B3=A8=E6=84=8F=E8=BF=94=E5=9B=9E=E5=80=BC=E5=92=8C=E5=8E=9F=E7= =89=88=E4=B8=8D=E4=B8=80=E6=A0=B7 +DWORD WaitForMultipleObjectsCustom(DWORD nCount, CONST HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds) { + // emacs sys_select =E4=B8=AD=E8=B0=83=E7=94=A8 WaitForMultipleObjects= =E6=97=B6 bWaitAll =E5=8F=82=E6=95=B0=E9=83=BD=E4=B8=BA FALSE + bWaitAll =3D FALSE; + if (nCount <=3D 64) { + // =E5=8F=A5=E6=9F=84=E6=95=B0=E6=9C=AA=E8=B6=85=E8=BF=87=E9=99=90= =E5=88=B6=EF=BC=8C=E7=9B=B4=E6=8E=A5=E8=B0=83=E7=94=A8 WaitForMultipleObjec= ts + DWORD result =3D WaitForMultipleObjects(nCount, lpHandles, bWaitAl= l, dwMilliseconds); + if (result >=3D WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + nCount) = { + return result - WAIT_OBJECT_0; + } else if (WAIT_TIMEOUT =3D=3D result) { + return MY_WAIT_TIMEOUT; + } else if (result >=3D WAIT_ABANDONED_0 && result < WAIT_ABANDONED= _0 + nCount) { + return result - WAIT_ABANDONED_0 + MY_WAIT_ABANDONED_0; + } else { + return MY_WAIT_FAILED; + } + } + + // =E5=B0=86=E5=8F=A5=E6=9F=84=E5=88=86=E7=BB=84=EF=BC=8C=E6=AF=8F=E7= =BB=84=E6=9C=80=E5=A4=9A MY_MAX_WAIT_OBJECTS =E4=B8=AA=E5=8F=A5=E6=9F=84 + int numGroups =3D (nCount + MY_MAX_WAIT_OBJECTS - 1) / MY_MAX_WAIT_OBJECTS; + HANDLE *groupCompletionEvents =3D (HANDLE *)malloc(numGroups * sizeof(HANDLE)); + WaitForThreadData *threadParams =3D (WaitForThreadData *)malloc(numGroups * sizeof(WaitForThreadData)); + HANDLE *threads =3D (HANDLE *)malloc(numGroups * sizeof(HANDLE)); + DWORD *threadResults =3D (DWORD *)malloc(numGroups * sizeof(DWORD)); + HANDLE *exitEvents =3D (HANDLE *)malloc(numGroups * sizeof(HANDLE)); /= / =E7=94=A8=E4=BA=8E=E6=8E=A7=E5=88=B6=E7=BA=BF=E7=A8=8B=E9=80=80=E5=87=BA + DWORD startTime =3D GetTickCount(); + DWORD elapsedTime =3D 0; + + for (int i =3D 0; i < numGroups; ++i) { + int groupCount =3D (i =3D=3D numGroups - 1) ? (nCount - i * MY_MAX_WAIT_OBJECTS) : MY_MAX_WAIT_OBJECTS; + threadParams[i].handles =3D (HANDLE *)(lpHandles + i * MY_MAX_WAIT_OBJECTS); + threadParams[i].count =3D groupCount; + threadParams[i].bWaitAll =3D bWaitAll; + threadParams[i].dwMilliseconds =3D dwMilliseconds; + threadParams[i].completionEvent =3D CreateEvent(NULL, FALSE, FALSE= , NULL); + threadParams[i].threadResult =3D &threadResults[i]; + threadParams[i].exitEvent =3D CreateEvent(NULL, TRUE, FALSE, NULL)= ; + groupCompletionEvents[i] =3D threadParams[i].completionEvent; + exitEvents[i] =3D threadParams[i].exitEvent; + + threads[i] =3D CreateThread(NULL, 0, WaitForThreadProc, &threadParams[i], 0, NULL); + } + + // =E7=AD=89=E5=BE=85=E4=BB=BB=E4=B8=80=E7=BB=84=E5=AE=8C=E6=88=90 + DWORD result; + if (dwMilliseconds !=3D INFINITE) { + DWORD remainingTime =3D dwMilliseconds - elapsedTime; + result =3D WaitForMultipleObjects(numGroups, groupCompletionEvents= , bWaitAll, remainingTime); + } else { + result =3D WaitForMultipleObjects(numGroups, groupCompletionEvents= , bWaitAll, dwMilliseconds); + } + + // =E9=80=9A=E7=9F=A5=E6=89=80=E6=9C=89=E7=BA=BF=E7=A8=8B=E9=80=80=E5= =87=BA + for (int i =3D 0; i < numGroups; ++i) { + SetEvent(exitEvents[i]); // =E6=96=B0=E5=A2=9E + } + + // =E8=8E=B7=E5=8F=96=E7=BB=93=E6=9E=9C + if (result >=3D WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + numGroups) { + DWORD inner_result =3D threadResults[result - WAIT_OBJECT_0]; + if (inner_result >=3D WAIT_OBJECT_0 && inner_result < WAIT_OBJECT_= 0 + threadParams[result - WAIT_OBJECT_0].count) { + result =3D inner_result + (result - WAIT_OBJECT_0) * MY_MAX_WAIT_OBJECTS; + } else if (inner_result >=3D WAIT_ABANDONED_0 && inner_result < WAIT_ABANDONED_0 + MY_MAX_WAIT_OBJECTS) { + result =3D inner_result - WAIT_ABANDONED_0 + MY_WAIT_ABANDONED= _0; + } else if (WAIT_TIMEOUT =3D=3D inner_result) { + result =3D MY_WAIT_TIMEOUT; + } else { + result =3D MY_WAIT_FAILED; + } + } else if (WAIT_TIMEOUT =3D=3D result) { + result =3D MY_WAIT_TIMEOUT; + } else if (result >=3D WAIT_ABANDONED_0 && result < WAIT_ABANDONED_0 + numGroups) { + result =3D result - WAIT_ABANDONED_0 + MY_WAIT_ABANDONED_0 ; + } else { + result =3D MY_WAIT_FAILED; + } + + // =E7=AD=89=E5=BE=85=E6=89=80=E6=9C=89=E7=BA=BF=E7=A8=8B=E7=BB=93=E6= =9D=9F + WaitForMultipleObjects(numGroups, threads, TRUE, INFINITE); + + // =E5=85=B3=E9=97=AD=E5=8F=A5=E6=9F=84=E5=92=8C=E9=87=8A=E6=94=BE=E8= =B5=84=E6=BA=90 + for (int i =3D 0; i < numGroups; ++i) { + CloseHandle(threads[i]); + CloseHandle(groupCompletionEvents[i]); + CloseHandle(exitEvents[i]); // =E6=96=B0=E5=A2=9E + } + + free(groupCompletionEvents); + free(threadParams); + free(threads); + free(threadResults); + free(exitEvents); // =E6=96=B0=E5=A2=9E + + return result; +} + +typedef struct { + DWORD nCount; + HANDLE* lpHandles; + BOOL bWaitAll; + DWORD dwMilliseconds; + HANDLE event; + HANDLE exitEvent; + DWORD threadResult; +} MsgWaitThreadData; + +DWORD WINAPI MsgWaitThreadFunction(LPVOID param) { + MsgWaitThreadData* data =3D (MsgWaitThreadData*)param; + HANDLE *allHandles =3D (HANDLE *)malloc((data->nCount + 1) * sizeof(HANDLE)); + memcpy(allHandles, data->lpHandles, data->nCount * sizeof(HANDLE)); + allHandles[data->nCount] =3D data->exitEvent; + DWORD result =3D WaitForMultipleObjectsCustom(data->nCount+1, allHandles, data->bWaitAll, data->dwMilliseconds); + // printf("WaitForMultipleObjectsCustom result: %lu\n", result); + if (result =3D=3D WAIT_OBJECT_0 + data->nCount) { + // exitEvent =E8=A2=AB=E8=A7=A6=E5=8F=91=EF=BC=8C=E7=BA=BF=E7=A8= =8B=E9=80=80=E5=87=BA + data->threadResult =3D MY_WAIT_FAILED; + } else { + data->threadResult =3D result; + } + + // =E9=80=9A=E7=9F=A5=E4=B8=BB=E7=BA=BF=E7=A8=8B=E8=AF=A5=E7=BB=84=E5= =B7=B2=E5=AE=8C=E6=88=90 + SetEvent(data->event); + free(allHandles); + + return 0; +} + +DWORD MsgWaitForMultipleObjectsCustom(DWORD nCount, HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, DWORD dwWakeMask) { + // emacs sys_select =E4=B8=AD=E8=B0=83=E7=94=A8 MsgWaitForMultipleObje= cts =E6=97=B6 bWaitAll =E5=8F=82=E6=95=B0=E9=83=BD=E4=B8=BA FALSE + bWaitAll =3D FALSE; + HANDLE event =3D CreateEvent(NULL, FALSE, FALSE, NULL); // completeEv= ent + if (event =3D=3D NULL) { + return MY_WAIT_FAILED; + } + HANDLE exitEvent =3D CreateEvent(NULL, FALSE, FALSE, NULL); + if (event =3D=3D NULL) { + return MY_WAIT_FAILED; + } + + MsgWaitThreadData data =3D { nCount, lpHandles, bWaitAll, dwMilliseconds, event, exitEvent, MY_WAIT_FAILED }; + HANDLE thread =3D CreateThread(NULL, 0, MsgWaitThreadFunction, &data, = 0, NULL); + if (thread =3D=3D NULL) { + CloseHandle(event); + return MY_WAIT_FAILED; + } + + DWORD result =3D MsgWaitForMultipleObjects(1, &event, FALSE, dwMilliseconds, dwWakeMask); + SetEvent(exitEvent); + // printf("MsgWaitForMultipleObjects result: %lu\n", result); + if (result =3D=3D WAIT_OBJECT_0) { + result =3D data.threadResult; + } else if (result =3D=3D WAIT_OBJECT_0 + 1) { + // =E6=B6=88=E6=81=AF=E9=98=9F=E5=88=97=E4=B8=AD=E6=9C=89=E6=B6=88= =E6=81=AF + result =3D WAIT_OBJECT_0 + nCount; // =E8=A1=A8=E7=A4=BA=E6=B6=88= =E6=81=AF=E9=98=9F=E5=88=97=E6=9C=89=E6=B6=88=E6=81=AF + } else if (result =3D=3D WAIT_TIMEOUT) { + result =3D MY_WAIT_TIMEOUT; + } else { + result =3D MY_WAIT_FAILED; // =E7=9B=B4=E6=8E=A5=E8=BF=94=E5=9B=9E= =E7=BB=93=E6=9E=9C + } + + WaitForSingleObject(thread, INFINITE); + + CloseHandle(exitEvent); + CloseHandle(event); + CloseHandle(thread); + return result; +} + void w32_raise (int); @@ -1566,15 +1775,15 @@ waitpid (pid_t pid, int *status, int options) quitting in that case. */ if (!dont_wait) maybe_quit (); - active =3D WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms); - } while (active =3D=3D WAIT_TIMEOUT && !dont_wait); + active =3D WaitForMultipleObjectsCustom (nh, wait_hnd, FALSE, timeout_ms); + } while (active =3D=3D MY_WAIT_TIMEOUT && !dont_wait); - if (active =3D=3D WAIT_FAILED) + if (active =3D=3D MY_WAIT_FAILED) { errno =3D EBADF; return -1; } - else if (active =3D=3D WAIT_TIMEOUT && dont_wait) + else if (active =3D=3D MY_WAIT_TIMEOUT && dont_wait) { /* PID specifies our subprocess, but it didn't exit yet, so its status is not yet available. */ @@ -1584,14 +1793,14 @@ waitpid (pid_t pid, int *status, int options) return 0; } else if (active >=3D WAIT_OBJECT_0 - && active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS) + && active < WAIT_OBJECT_0+MY_MAXIMUM_WAIT_OBJECTS) { active -=3D WAIT_OBJECT_0; } - else if (active >=3D WAIT_ABANDONED_0 - && active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS) + else if (active >=3D MY_WAIT_ABANDONED_0 + && active < MY_WAIT_ABANDONED_0+MY_MAXIMUM_WAIT_OBJECTS) { - active -=3D WAIT_ABANDONED_0; + active -=3D MY_WAIT_ABANDONED_0; } else emacs_abort (); @@ -2500,13 +2709,15 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, /* Wait for input or child death to be signaled. If user input is allowed, then also accept window messages. */ - if (FD_ISSET (0, &orfds)) - active =3D MsgWaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_ms, - QS_ALLINPUT); + if (FD_ISSET (0, &orfds)){ + active =3D MsgWaitForMultipleObjectsCustom (nh + nc, wait_hnd, FALSE, timeout_ms, + QS_ALLINPUT); + } + else - active =3D WaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_m= s); + active =3D WaitForMultipleObjectsCustom (nh + nc, wait_hnd, FALSE, timeout_ms); - if (active =3D=3D WAIT_FAILED) + if (active =3D=3D MY_WAIT_FAILED) { DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n", nh + nc, timeout_ms, GetLastError ())); @@ -2517,7 +2728,7 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, errno =3D EINTR; return -1; } - else if (active =3D=3D WAIT_TIMEOUT) + else if (active =3D=3D MY_WAIT_TIMEOUT) { if (noninteractive) { @@ -2527,14 +2738,14 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, return 0; } else if (active >=3D WAIT_OBJECT_0 - && active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS) + && active < WAIT_OBJECT_0+MY_MAXIMUM_WAIT_OBJECTS) { active -=3D WAIT_OBJECT_0; } - else if (active >=3D WAIT_ABANDONED_0 - && active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS) + else if (active >=3D MY_WAIT_ABANDONED_0 + && active < MY_WAIT_ABANDONED_0+MY_MAXIMUM_WAIT_OBJECTS) { - active -=3D WAIT_ABANDONED_0; + active -=3D MY_WAIT_ABANDONED_0; } else emacs_abort (); --0000000000004ea112061afe367d Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
the related discusstion is here https://emacs-china.org/t/windows= -emacs-2024-6-16/27392
I modified from github commit 08e38818f6ff4e5= 14ac291bc5a7686f4390759b0 .


1 in build phase
add macro -DFD_S= ETSIZE=3D4096

2 modify w32.h and w32pro.h
git diff is below
diff --git a/src/w32.h b/src/w32.h
index cf470ae9901..0340f10e62b 1006= 44
--- a/src/w32.h
+++ b/src/w32.h
@@ -29,7 +29,7 @@ along with GN= U Emacs.=C2=A0 If not, see <ht= tps://www.gnu.org/licenses/>. =C2=A0*/
=C2=A0/* File descriptor s= et emulation. =C2=A0*/
=C2=A0
=C2=A0/* MSVC runtime library has limit= of 64 descriptors by default */
-#define FD_SETSIZE =C2=A064
+#defin= e FD_SETSIZE =C2=A04096
=C2=A0typedef struct {
=C2=A0 =C2=A0unsigned = int bits[FD_SETSIZE / 32];
=C2=A0} fd_set;
diff --git a/src/w32proc.c= b/src/w32proc.c
index 40181e09830..60918cb4a41 100644
--- a/src/w32p= roc.c
+++ b/src/w32proc.c
@@ -62,6 +62,215 @@ along with GNU Emacs.= =C2=A0 If not, see <https://ww= w.gnu.org/licenses/>. =C2=A0*/
=C2=A0#include "syssignal.h&q= uot;
=C2=A0#include "w32term.h"
=C2=A0#include "coding= .h"
+#include <windows.h>
+
+#define MY_MAXIMUM_WAIT_OB= JECTS 4096
+// =E6=9C=80=E5=A4=A7=E7=AD=89=E5=BE=85=E5=AF=B9=E8=B1=A1=E6= =95=B0=EF=BC=8C=E9=A2=9D=E5=A4=96=E7=9A=84=E4=B8=80=E4=B8=AA=E7=94=A8=E4=BA= =8E=E7=BA=BF=E7=A8=8B=E9=80=80=E5=87=BAevent
+#define MY_MAX_WAIT_OBJECT= S 63
+#define MY_WAIT_TIMEOUT 0x9999
+#define MY_WAIT_FAILED 0x9998+#define MY_WAIT_ABANDONED_0 0x5000
+
+
+// =E7=BA=BF=E7=A8=8B= =E5=8F=82=E6=95=B0=E7=BB=93=E6=9E=84
+typedef struct {
+ =C2=A0 =C2= =A0HANDLE *handles;
+ =C2=A0 =C2=A0int count;
+ =C2=A0 =C2=A0BOOL bWa= itAll;
+ =C2=A0 =C2=A0DWORD dwMilliseconds;
+ =C2=A0 =C2=A0HANDLE com= pletionEvent; // =E7=94=A8=E4=BA=8E=E9=80=9A=E7=9F=A5=E4=B8=BB=E7=BA=BF=E7= =A8=8B=E8=AF=A5=E7=BA=BF=E7=A8=8B=E7=9A=84WaitForMultipleObjects=E5=B7=B2= =E5=AE=8C=E6=88=90
+ =C2=A0 =C2=A0DWORD *threadResult; // =E8=8E=B7=E5= =8F=96=E7=BA=BF=E7=A8=8B=E8=B0=83=E7=94=A8WaitForMultipleObjects=E7=9A=84= =E8=BF=94=E5=9B=9E=E5=80=BC
+ =C2=A0 =C2=A0HANDLE exitEvent; // =E7=94= =A8=E4=BA=8E=E6=8E=A7=E5=88=B6=E7=BA=BF=E7=A8=8B=E9=80=80=E5=87=BA
+} Wa= itForThreadData;
+
+// =E7=BA=BF=E7=A8=8B=E5=87=BD=E6=95=B0=EF=BC=8C= =E7=AD=89=E5=BE=85=E4=B8=80=E7=BB=84=E5=8F=A5=E6=9F=84
+DWORD WINAPI Wai= tForThreadProc(LPVOID lpParam) {
+ =C2=A0 =C2=A0WaitForThreadData *param= s =3D (WaitForThreadData *)lpParam;
+ =C2=A0 =C2=A0HANDLE *allHandles = =3D (HANDLE *)malloc((params->count + 1) * sizeof(HANDLE));
+ =C2=A0 = =C2=A0memcpy(allHandles, params->handles, params->count * sizeof(HAND= LE));
+ =C2=A0 =C2=A0allHandles[params->count] =3D params->exitEve= nt;
+
+ =C2=A0 =C2=A0DWORD result =3D WaitForMultipleObjects(params-= >count + 1, allHandles, params->bWaitAll, params->dwMilliseconds);=
+ =C2=A0 =C2=A0if (result =3D=3D WAIT_OBJECT_0 + params->count) {+ =C2=A0 =C2=A0 =C2=A0 =C2=A0// exitEvent =E8=A2=AB=E8=A7=A6=E5=8F=91=EF= =BC=8C=E7=BA=BF=E7=A8=8B=E9=80=80=E5=87=BA
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0= result =3D WAIT_TIMEOUT;
+ =C2=A0 =C2=A0} else {
+ =C2=A0 =C2=A0 =C2= =A0 =C2=A0*params->threadResult =3D result;
+ =C2=A0 =C2=A0}
+
= + =C2=A0 =C2=A0// =E9=80=9A=E7=9F=A5=E4=B8=BB=E7=BA=BF=E7=A8=8B=E8=AF=A5=E7= =BB=84=E5=B7=B2=E5=AE=8C=E6=88=90
+ =C2=A0 =C2=A0SetEvent(params->com= pletionEvent);
+ =C2=A0 =C2=A0free(allHandles);
+ =C2=A0 =C2=A0return= result;
+}
+// =E6=89=A9=E5=B1=95=E7=9A=84 WaitForMultipleObjects = =E5=87=BD=E6=95=B0 =EF=BC=8C=E6=B3=A8=E6=84=8F=E8=BF=94=E5=9B=9E=E5=80=BC= =E5=92=8C=E5=8E=9F=E7=89=88=E4=B8=8D=E4=B8=80=E6=A0=B7
+DWORD WaitForMul= tipleObjectsCustom(DWORD nCount, CONST HANDLE *lpHandles, BOOL bWaitAll, DW= ORD dwMilliseconds) {
+ =C2=A0 =C2=A0// emacs sys_select =E4=B8=AD=E8=B0= =83=E7=94=A8 WaitForMultipleObjects =E6=97=B6 bWaitAll =E5=8F=82=E6=95=B0= =E9=83=BD=E4=B8=BA FALSE
+ =C2=A0 =C2=A0bWaitAll =3D FALSE;
+ =C2=A0 = =C2=A0if (nCount <=3D 64) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0// =E5=8F=A5= =E6=9F=84=E6=95=B0=E6=9C=AA=E8=B6=85=E8=BF=87=E9=99=90=E5=88=B6=EF=BC=8C=E7= =9B=B4=E6=8E=A5=E8=B0=83=E7=94=A8 WaitForMultipleObjects
+ =C2=A0 =C2=A0= =C2=A0 =C2=A0DWORD result =3D WaitForMultipleObjects(nCount, lpHandles, bW= aitAll, dwMilliseconds);
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0if (result >=3D= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + nCount) {
+ =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return result - WAIT_OBJECT_0;
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0} else if (WAIT_TIMEOUT =3D=3D result) {
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return MY_WAIT_TIMEOUT;
+ =C2=A0 = =C2=A0 =C2=A0 =C2=A0} else if (result >=3D WAIT_ABANDONED_0 && r= esult < WAIT_ABANDONED_0 + nCount) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0return result - WAIT_ABANDONED_0 + MY_WAIT_ABANDONED_0;
+ = =C2=A0 =C2=A0 =C2=A0 =C2=A0} else {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0return MY_WAIT_FAILED;
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0}
+ =C2=A0= =C2=A0}
+
+ =C2=A0 =C2=A0// =E5=B0=86=E5=8F=A5=E6=9F=84=E5=88=86=E7= =BB=84=EF=BC=8C=E6=AF=8F=E7=BB=84=E6=9C=80=E5=A4=9A MY_MAX_WAIT_OBJECTS =E4= =B8=AA=E5=8F=A5=E6=9F=84
+ =C2=A0 =C2=A0int numGroups =3D (nCount + MY_M= AX_WAIT_OBJECTS - 1) / MY_MAX_WAIT_OBJECTS;
+ =C2=A0 =C2=A0HANDLE *group= CompletionEvents =3D (HANDLE *)malloc(numGroups * sizeof(HANDLE));
+ =C2= =A0 =C2=A0WaitForThreadData *threadParams =3D (WaitForThreadData *)malloc(n= umGroups * sizeof(WaitForThreadData));
+ =C2=A0 =C2=A0HANDLE *threads = =3D (HANDLE *)malloc(numGroups * sizeof(HANDLE));
+ =C2=A0 =C2=A0DWORD *= threadResults =3D (DWORD *)malloc(numGroups * sizeof(DWORD));
+ =C2=A0 = =C2=A0HANDLE *exitEvents =3D (HANDLE *)malloc(numGroups * sizeof(HANDLE)); = // =E7=94=A8=E4=BA=8E=E6=8E=A7=E5=88=B6=E7=BA=BF=E7=A8=8B=E9=80=80=E5=87=BA=
+ =C2=A0 =C2=A0DWORD startTime =3D GetTickCount();
+ =C2=A0 =C2=A0DW= ORD elapsedTime =3D 0;
+
+ =C2=A0 =C2=A0for (int i =3D 0; i < numG= roups; ++i) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0int groupCount =3D (i =3D=3D = numGroups - 1) ? (nCount - i * MY_MAX_WAIT_OBJECTS) : MY_MAX_WAIT_OBJECTS;<= br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0threadParams[i].handles =3D (HANDLE *)(lpHa= ndles + i * MY_MAX_WAIT_OBJECTS);
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0threadPar= ams[i].count =3D groupCount;
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0threadParams[i= ].bWaitAll =3D bWaitAll;
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0threadParams[i].dw= Milliseconds =3D dwMilliseconds;
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0threadPara= ms[i].completionEvent =3D CreateEvent(NULL, FALSE, FALSE, NULL);
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0threadParams[i].threadResult =3D &threadResults= [i];
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0threadParams[i].exitEvent =3D CreateEv= ent(NULL, TRUE, FALSE, NULL);
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0groupComplet= ionEvents[i] =3D threadParams[i].completionEvent;
+ =C2=A0 =C2=A0 =C2=A0= =C2=A0exitEvents[i] =3D threadParams[i].exitEvent;
+
+ =C2=A0 =C2= =A0 =C2=A0 =C2=A0threads[i] =3D CreateThread(NULL, 0, WaitForThreadProc, &a= mp;threadParams[i], 0, NULL);
+ =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0//= =E7=AD=89=E5=BE=85=E4=BB=BB=E4=B8=80=E7=BB=84=E5=AE=8C=E6=88=90
+ =C2= =A0 =C2=A0DWORD result;
+ =C2=A0 =C2=A0if (dwMilliseconds !=3D INFINITE)= {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0DWORD remainingTime =3D dwMilliseconds -= elapsedTime;
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0result =3D WaitForMultipleObj= ects(numGroups, groupCompletionEvents, bWaitAll, remainingTime);
+ =C2= =A0 =C2=A0} else {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0result =3D WaitForMultip= leObjects(numGroups, groupCompletionEvents, bWaitAll, dwMilliseconds);
+= =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0// =E9=80=9A=E7=9F=A5=E6=89=80=E6=9C= =89=E7=BA=BF=E7=A8=8B=E9=80=80=E5=87=BA
+ =C2=A0 =C2=A0for (int i =3D 0;= i < numGroups; ++i) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0SetEvent(exitEven= ts[i]); // =E6=96=B0=E5=A2=9E
+ =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0//= =E8=8E=B7=E5=8F=96=E7=BB=93=E6=9E=9C
+ =C2=A0 =C2=A0if (result >=3D = WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + numGroups) {
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0DWORD inner_result =3D threadResults[result - WAIT_= OBJECT_0];
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0if (inner_result >=3D WAIT_OB= JECT_0 && inner_result < WAIT_OBJECT_0 + threadParams[result - W= AIT_OBJECT_0].count) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0result= =3D inner_result + (result - WAIT_OBJECT_0) * MY_MAX_WAIT_OBJECTS;
+ = =C2=A0 =C2=A0 =C2=A0 =C2=A0} else if (inner_result >=3D WAIT_ABANDONED_0= && inner_result < WAIT_ABANDONED_0 + MY_MAX_WAIT_OBJECTS) {
= + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0result =3D inner_result - WAIT_A= BANDONED_0 + MY_WAIT_ABANDONED_0;
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0} else if= (WAIT_TIMEOUT =3D=3D inner_result) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0result =3D MY_WAIT_TIMEOUT;
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0} els= e {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0result =3D MY_WAIT_FAILED= ;
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0}
+ =C2=A0 =C2=A0} else if (WAIT_TIMEO= UT =3D=3D result) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0result =3D MY_WAIT_TIME= OUT;
+ =C2=A0 =C2=A0} else if (result >=3D WAIT_ABANDONED_0 &&= ; result < WAIT_ABANDONED_0 + numGroups) {
+ =C2=A0 =C2=A0 =C2=A0 =C2= =A0result =3D result - WAIT_ABANDONED_0 + MY_WAIT_ABANDONED_0 ;
+ =C2=A0= =C2=A0} else {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0result =3D MY_WAIT_FAILED;<= br>+ =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0// =E7=AD=89=E5=BE=85=E6=89=80= =E6=9C=89=E7=BA=BF=E7=A8=8B=E7=BB=93=E6=9D=9F
+ =C2=A0 =C2=A0WaitForMult= ipleObjects(numGroups, threads, TRUE, INFINITE);
+
+ =C2=A0 =C2=A0// = =E5=85=B3=E9=97=AD=E5=8F=A5=E6=9F=84=E5=92=8C=E9=87=8A=E6=94=BE=E8=B5=84=E6= =BA=90
+ =C2=A0 =C2=A0for (int i =3D 0; i < numGroups; ++i) {
+ = =C2=A0 =C2=A0 =C2=A0 =C2=A0CloseHandle(threads[i]);
+ =C2=A0 =C2=A0 =C2= =A0 =C2=A0CloseHandle(groupCompletionEvents[i]);
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0CloseHandle(exitEvents[i]); // =E6=96=B0=E5=A2=9E
+ =C2=A0 =C2=A0}=
+
+ =C2=A0 =C2=A0free(groupCompletionEvents);
+ =C2=A0 =C2=A0free= (threadParams);
+ =C2=A0 =C2=A0free(threads);
+ =C2=A0 =C2=A0free(thr= eadResults);
+ =C2=A0 =C2=A0free(exitEvents); // =E6=96=B0=E5=A2=9E
+=
+ =C2=A0 =C2=A0return result;
+}
+
+typedef struct {
+ =C2= =A0 =C2=A0DWORD nCount;
+ =C2=A0 =C2=A0HANDLE* lpHandles;
+ =C2=A0 = =C2=A0BOOL bWaitAll;
+ =C2=A0 =C2=A0DWORD dwMilliseconds;
+ =C2=A0 = =C2=A0HANDLE event;
+ =C2=A0 =C2=A0HANDLE exitEvent;
+ =C2=A0 =C2=A0D= WORD threadResult;
+} MsgWaitThreadData;
+
+DWORD WINAPI MsgWaitTh= readFunction(LPVOID param) {
+ =C2=A0 =C2=A0MsgWaitThreadData* data =3D = (MsgWaitThreadData*)param;
+ =C2=A0 =C2=A0HANDLE *allHandles =3D (HANDLE= *)malloc((data->nCount + 1) * sizeof(HANDLE));
+ =C2=A0 =C2=A0memcpy= (allHandles, data->lpHandles, data->nCount * sizeof(HANDLE));
+ = =C2=A0 =C2=A0allHandles[data->nCount] =3D data->exitEvent;
+ =C2= =A0 =C2=A0DWORD result =3D WaitForMultipleObjectsCustom(data->nCount+1, = allHandles, data->bWaitAll, data->dwMilliseconds);
+ =C2=A0 =C2=A0= // printf("WaitForMultipleObjectsCustom result: %lu\n", result);<= br>+ =C2=A0 =C2=A0if (result =3D=3D WAIT_OBJECT_0 + data->nCount) {
+= =C2=A0 =C2=A0 =C2=A0 =C2=A0// exitEvent =E8=A2=AB=E8=A7=A6=E5=8F=91=EF=BC= =8C=E7=BA=BF=E7=A8=8B=E9=80=80=E5=87=BA
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0dat= a->threadResult =3D MY_WAIT_FAILED;
+ =C2=A0 =C2=A0} else {
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0data->threadResult =3D result;
+ =C2=A0 =C2= =A0}
+
+ =C2=A0 =C2=A0// =E9=80=9A=E7=9F=A5=E4=B8=BB=E7=BA=BF=E7=A8= =8B=E8=AF=A5=E7=BB=84=E5=B7=B2=E5=AE=8C=E6=88=90
+ =C2=A0 =C2=A0SetEvent= (data->event);
+ =C2=A0 =C2=A0free(allHandles);
+
+ =C2=A0 =C2= =A0return 0;
+}
+
+DWORD MsgWaitForMultipleObjectsCustom(DWORD nCo= unt, HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, DWORD dwWakeMa= sk) {
+ =C2=A0 =C2=A0// emacs sys_select =E4=B8=AD=E8=B0=83=E7=94=A8 Msg= WaitForMultipleObjects =E6=97=B6 bWaitAll =E5=8F=82=E6=95=B0=E9=83=BD=E4=B8= =BA FALSE
+ =C2=A0 =C2=A0bWaitAll =3D FALSE;
+ =C2=A0 =C2=A0HANDLE ev= ent =3D CreateEvent(NULL, FALSE, FALSE, NULL); =C2=A0// completeEvent
+ = =C2=A0 =C2=A0if (event =3D=3D NULL) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0retur= n MY_WAIT_FAILED;
+ =C2=A0 =C2=A0}
+ =C2=A0 =C2=A0HANDLE exitEvent = =3D CreateEvent(NULL, FALSE, FALSE, NULL);
+ =C2=A0 =C2=A0if (event =3D= =3D NULL) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0return MY_WAIT_FAILED;
+ =C2= =A0 =C2=A0}
+
+ =C2=A0 =C2=A0MsgWaitThreadData data =3D { nCount, lpH= andles, bWaitAll, dwMilliseconds, event, exitEvent, MY_WAIT_FAILED };
+ = =C2=A0 =C2=A0HANDLE thread =3D CreateThread(NULL, 0, MsgWaitThreadFunction,= &data, 0, NULL);
+ =C2=A0 =C2=A0if (thread =3D=3D NULL) {
+ =C2= =A0 =C2=A0 =C2=A0 =C2=A0CloseHandle(event);
+ =C2=A0 =C2=A0 =C2=A0 =C2= =A0return MY_WAIT_FAILED;
+ =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0DWORD = result =3D MsgWaitForMultipleObjects(1, &event, FALSE, dwMilliseconds, = dwWakeMask);
+ =C2=A0 =C2=A0SetEvent(exitEvent);
+ =C2=A0 =C2=A0// p= rintf("MsgWaitForMultipleObjects result: %lu\n", result);
+ = =C2=A0 =C2=A0if (result =3D=3D WAIT_OBJECT_0) {
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0result =3D data.threadResult;
+ =C2=A0 =C2=A0} else if (result =3D= =3D WAIT_OBJECT_0 + 1) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0// =E6=B6=88=E6=81= =AF=E9=98=9F=E5=88=97=E4=B8=AD=E6=9C=89=E6=B6=88=E6=81=AF
+ =C2=A0 =C2= =A0 =C2=A0 =C2=A0result =3D =C2=A0WAIT_OBJECT_0 + nCount; // =E8=A1=A8=E7= =A4=BA=E6=B6=88=E6=81=AF=E9=98=9F=E5=88=97=E6=9C=89=E6=B6=88=E6=81=AF
+ = =C2=A0 =C2=A0} else if (result =3D=3D WAIT_TIMEOUT) {
+ =C2=A0 =C2=A0 = =C2=A0 =C2=A0result =3D MY_WAIT_TIMEOUT;
+ =C2=A0 =C2=A0} else {
+ = =C2=A0 =C2=A0 =C2=A0 =C2=A0result =3D MY_WAIT_FAILED; // =E7=9B=B4=E6=8E=A5= =E8=BF=94=E5=9B=9E=E7=BB=93=E6=9E=9C
+ =C2=A0 =C2=A0}
+
+ =C2=A0 = =C2=A0WaitForSingleObject(thread, INFINITE);
+
+ =C2=A0 =C2=A0CloseHa= ndle(exitEvent);
+ =C2=A0 =C2=A0CloseHandle(event);
+ =C2=A0 =C2=A0Cl= oseHandle(thread);
+ =C2=A0 =C2=A0return result;
+}
+
=C2=A0=C2=A0void w32_raise (int);
=C2=A0
@@ -1566,15 +1775,15 @@ waitpid (= pid_t pid, int *status, int options)
=C2=A0 quitting in that case. =C2= =A0*/
=C2=A0 =C2=A0 =C2=A0 =C2=A0if (!dont_wait)
=C2=A0 maybe_quit ()= ;
- =C2=A0 =C2=A0 =C2=A0active =3D WaitForMultipleObjects (nh, wait_hnd,= FALSE, timeout_ms);
- =C2=A0 =C2=A0} while (active =3D=3D WAIT_TIMEOUT = && !dont_wait);
+ =C2=A0 =C2=A0 =C2=A0active =3D WaitForMultiple= ObjectsCustom (nh, wait_hnd, FALSE, timeout_ms);
+ =C2=A0 =C2=A0} while = (active =3D=3D MY_WAIT_TIMEOUT && !dont_wait);
=C2=A0
- =C2= =A0if (active =3D=3D WAIT_FAILED)
+ =C2=A0if (active =3D=3D MY_WAIT_FAIL= ED)
=C2=A0 =C2=A0 =C2=A0{
=C2=A0 =C2=A0 =C2=A0 =C2=A0errno =3D EBADF;=
=C2=A0 =C2=A0 =C2=A0 =C2=A0return -1;
=C2=A0 =C2=A0 =C2=A0}
- =C2= =A0else if (active =3D=3D WAIT_TIMEOUT && dont_wait)
+ =C2=A0els= e if (active =3D=3D MY_WAIT_TIMEOUT && dont_wait)
=C2=A0 =C2=A0 = =C2=A0{
=C2=A0 =C2=A0 =C2=A0 =C2=A0/* PID specifies our subprocess, but = it didn't exit yet, so its
=C2=A0 status is not yet available. =C2= =A0*/
@@ -1584,14 +1793,14 @@ waitpid (pid_t pid, int *status, int optio= ns)
=C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
=C2=A0 =C2=A0 =C2=A0}
=C2= =A0 =C2=A0else if (active >=3D WAIT_OBJECT_0
- =C2=A0 && act= ive < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
+ =C2=A0 && active= < WAIT_OBJECT_0+MY_MAXIMUM_WAIT_OBJECTS)
=C2=A0 =C2=A0 =C2=A0{
= =C2=A0 =C2=A0 =C2=A0 =C2=A0active -=3D WAIT_OBJECT_0;
=C2=A0 =C2=A0 =C2= =A0}
- =C2=A0else if (active >=3D WAIT_ABANDONED_0
- =C2=A0 &= & active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS)
+ =C2=A0else if= (active >=3D MY_WAIT_ABANDONED_0
+ =C2=A0 && active < MY= _WAIT_ABANDONED_0+MY_MAXIMUM_WAIT_OBJECTS)
=C2=A0 =C2=A0 =C2=A0{
- = =C2=A0 =C2=A0 =C2=A0active -=3D WAIT_ABANDONED_0;
+ =C2=A0 =C2=A0 =C2=A0= active -=3D MY_WAIT_ABANDONED_0;
=C2=A0 =C2=A0 =C2=A0}
=C2=A0 =C2=A0e= lse
=C2=A0 =C2=A0 =C2=A0emacs_abort ();
@@ -2500,13 +2709,15 @@ sys_s= elect (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,=C2=A0
=C2=A0 =C2=A0/* Wait for input or child death to be signaled.= =C2=A0 If user input is
=C2=A0 =C2=A0 =C2=A0 allowed, then also accept w= indow messages. =C2=A0*/
- =C2=A0if (FD_ISSET (0, &orfds))
- =C2= =A0 =C2=A0active =3D MsgWaitForMultipleObjects (nh + nc, wait_hnd, FALSE, t= imeout_ms,
- QS_ALLINPUT);
+ =C2=A0if (FD_ISSET (0, &orfds)){=
+ =C2=A0 =C2=A0active =3D MsgWaitForMultipleObjectsCustom (nh + nc, wai= t_hnd, FALSE, timeout_ms,
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0QS_ALLINPUT);
+ =C2=A0}
+ =C2=A0 =C2=A0
=C2=A0 =C2=A0else- =C2=A0 =C2=A0active =3D WaitForMultipleObjects (nh + nc, wait_hnd, FALSE= , timeout_ms);
+ =C2=A0 =C2=A0active =3D WaitForMultipleObjectsCustom (n= h + nc, wait_hnd, FALSE, timeout_ms);
=C2=A0
- =C2=A0if (active =3D= =3D WAIT_FAILED)
+ =C2=A0if (active =3D=3D MY_WAIT_FAILED)
=C2=A0 =C2= =A0 =C2=A0{
=C2=A0 =C2=A0 =C2=A0 =C2=A0DebPrint (("select.WaitForMu= ltipleObjects (%d, %lu) failed with %lu\n",
=C2=A0 nh + nc, timeo= ut_ms, GetLastError ()));
@@ -2517,7 +2728,7 @@ sys_select (int nfds, SE= LECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
=C2=A0 =C2=A0 =C2= =A0 =C2=A0errno =3D EINTR;
=C2=A0 =C2=A0 =C2=A0 =C2=A0return -1;
=C2= =A0 =C2=A0 =C2=A0}
- =C2=A0else if (active =3D=3D WAIT_TIMEOUT)
+ =C2= =A0else if (active =3D=3D MY_WAIT_TIMEOUT)
=C2=A0 =C2=A0 =C2=A0{
=C2= =A0 =C2=A0 =C2=A0 =C2=A0if (noninteractive)
=C2=A0 {
@@ -2527,14 +273= 8,14 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_= TYPE *efds,
=C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
=C2=A0 =C2=A0 =C2=A0= }
=C2=A0 =C2=A0else if (active >=3D WAIT_OBJECT_0
- =C2=A0 &&= amp; active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
+ =C2=A0 &&= ; active < WAIT_OBJECT_0+MY_MAXIMUM_WAIT_OBJECTS)
=C2=A0 =C2=A0 =C2= =A0{
=C2=A0 =C2=A0 =C2=A0 =C2=A0active -=3D WAIT_OBJECT_0;
=C2=A0 =C2= =A0 =C2=A0}
- =C2=A0else if (active >=3D WAIT_ABANDONED_0
- =C2= =A0 && active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS)
+ =C2= =A0else if (active >=3D MY_WAIT_ABANDONED_0
+ =C2=A0 && acti= ve < MY_WAIT_ABANDONED_0+MY_MAXIMUM_WAIT_OBJECTS)
=C2=A0 =C2=A0 =C2= =A0{
- =C2=A0 =C2=A0 =C2=A0active -=3D WAIT_ABANDONED_0;
+ =C2=A0 =C2= =A0 =C2=A0active -=3D MY_WAIT_ABANDONED_0;
=C2=A0 =C2=A0 =C2=A0}
=C2= =A0 =C2=A0else
=C2=A0 =C2=A0 =C2=A0emacs_abort ();
--0000000000004ea112061afe367d--