From cd73469b0119000d54355f098b78c818c9d8385a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20Svensson?= Date: Fri, 15 Oct 2021 20:25:53 +0200 Subject: [PATCH] Bug 574131: SIGTERM should let app do a gracefully exit on win MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let the process have some time to do a graceful exit with the signal SIGTERM. If the process is still alive after 1s, raise the SIGKILL signal and hammer down the process. The 1s is aligned on all platforms and handled in JAVA. Contributed by STMicroelectronics Change-Id: Iff2f7727c1ac37b190c60a01774f106638eeeeaa Signed-off-by: Torbjörn Svensson --- .../META-INF/MANIFEST.MF | 2 +- .../native_src/win/starter.c | 84 +++++++++--------- core/org.eclipse.cdt.core.native/pom.xml | 2 +- .../os/win32/x86_64/starter.exe | Bin 402864 -> 403406 bytes 4 files changed, 46 insertions(+), 42 deletions(-) diff --git a/core/org.eclipse.cdt.core.native/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core.native/META-INF/MANIFEST.MF index 9ec7bd30317..02504aa6729 100644 --- a/core/org.eclipse.cdt.core.native/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core.native/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.cdt.core.native;singleton:=true -Bundle-Version: 6.1.300.qualifier +Bundle-Version: 6.1.400.qualifier Bundle-Activator: org.eclipse.cdt.internal.core.natives.CNativePlugin Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/core/org.eclipse.cdt.core.native/native_src/win/starter.c b/core/org.eclipse.cdt.core.native/native_src/win/starter.c index 0e20b9257d4..690c21246b9 100644 --- a/core/org.eclipse.cdt.core.native/native_src/win/starter.c +++ b/core/org.eclipse.cdt.core.native/native_src/win/starter.c @@ -246,6 +246,20 @@ bool createCommandLine(int argc, wchar_t **argv, wchar_t **cmdLine) { return true; } +void raiseSignal(HANDLE h, int pid, const wchar_t *signal) { + if (isCygwin(h)) { + // Need to issue a kill command + wchar_t kill[1024]; + swprintf(kill, sizeof(kill) / sizeof(kill[0]), L"kill -%s %d", signal, pid); + if (!runCygwinCommand(kill)) { + // fall back to console event + GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); + } + } else { + GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); + } +} + int main() { int argc; @@ -384,24 +398,23 @@ int main() { } } +#define SIGINT_EVENT (WAIT_OBJECT_0 + 0) +#define EXIT_EVENT (WAIT_OBJECT_0 + 1) +#define SIGTERM_EVENT (WAIT_OBJECT_0 + 2) +#define SIGKILL_EVENT (WAIT_OBJECT_0 + 3) +#define CTRLC_EVENT (WAIT_OBJECT_0 + 4) while (!exitProc) { // Wait for the spawned-process to die or for the event // indicating that the processes should be forcibly killed. DWORD event = WaitForMultipleObjects(5, h, FALSE, INFINITE); switch (event) { - case WAIT_OBJECT_0 + 0: // SIGINT - case WAIT_OBJECT_0 + 4: // CTRL-C + case SIGINT_EVENT: + case CTRLC_EVENT: if (isTraceEnabled(CDT_TRACE_SPAWNER)) { cdtTrace(L"starter (PID %i) received CTRL-C event\n", GetCurrentProcessId()); } - if ((event == (WAIT_OBJECT_0 + 0)) && isCygwin(h[1])) { - // Need to issue a kill command - wchar_t kill[1024]; - swprintf(kill, sizeof(kill) / sizeof(kill[0]), L"kill -SIGINT %d", pi.dwProcessId); - if (!runCygwinCommand(kill)) { - // fall back to console event - GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); - } + if (event == SIGINT_EVENT) { + raiseSignal(h[1], pi.dwProcessId, L"SIGINT"); } else { GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); } @@ -409,8 +422,8 @@ int main() { SetEvent(waitEvent); break; - case WAIT_OBJECT_0 + 1: // App terminated normally - // Make it's exit code our exit code + case EXIT_EVENT: // App terminated normally + // Make it's exit code our exit code if (isTraceEnabled(CDT_TRACE_SPAWNER)) { cdtTrace(L"starter: launched process has been terminated(PID %i)\n", pi.dwProcessId); } @@ -418,43 +431,34 @@ int main() { exitProc = TRUE; break; - // Terminate and Kill behavior differ only for cygwin processes, where - // we use the cygwin 'kill' command. We send a SIGKILL in one case, - // SIGTERM in the other. For non-cygwin processes, both requests - // are treated exactly the same - case WAIT_OBJECT_0 + 2: // TERM - case WAIT_OBJECT_0 + 3: // KILL - { - const wchar_t *signal = (event == WAIT_OBJECT_0 + 2) ? L"TERM" : L"KILL"; + case SIGTERM_EVENT: if (isTraceEnabled(CDT_TRACE_SPAWNER)) { - cdtTrace(L"starter received %s event (PID %i)\n", signal, GetCurrentProcessId()); - } - if (isCygwin(h[1])) { - // Need to issue a kill command - wchar_t kill[1024]; - swprintf(kill, sizeof(kill) / sizeof(kill[0]), L"kill -%s %d", signal, pi.dwProcessId); - if (!runCygwinCommand(kill)) { - // fall back to console event - GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); - } - } else { - GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); + cdtTrace(L"starter received TERM event (PID %i)\n", GetCurrentProcessId()); } + raiseSignal(h[1], pi.dwProcessId, L"TERM"); SetEvent(waitEvent); - if (hJob) { - if (!TerminateJobObject(hJob, (DWORD)-1)) { - if (isTraceEnabled(CDT_TRACE_SPAWNER)) { - cdtTrace(L"Cannot terminate job\n"); - DisplayErrorMessage(); - } + // Note that we keep trucking until the child process terminates (case EXIT_EVENT) + break; + + case SIGKILL_EVENT: + if (isTraceEnabled(CDT_TRACE_SPAWNER)) { + cdtTrace(L"starter received KILL event (PID %i)\n", GetCurrentProcessId()); + } + + raiseSignal(h[1], pi.dwProcessId, L"KILL"); + SetEvent(waitEvent); + + if (hJob && !TerminateJobObject(hJob, (DWORD)-1)) { + if (isTraceEnabled(CDT_TRACE_SPAWNER)) { + cdtTrace(L"Cannot terminate job\n"); + DisplayErrorMessage(); } } - // Note that we keep trucking until the child process terminates (case WAIT_OBJECT_0 + 1) + // Note that we keep trucking until the child process terminates (case EXIT_EVENT) break; - } default: // Unexpected code diff --git a/core/org.eclipse.cdt.core.native/pom.xml b/core/org.eclipse.cdt.core.native/pom.xml index cadc6fc2ce8..7902b6315fe 100644 --- a/core/org.eclipse.cdt.core.native/pom.xml +++ b/core/org.eclipse.cdt.core.native/pom.xml @@ -23,7 +23,7 @@ ../../pom.xml - 6.1.300-SNAPSHOT + 6.1.400-SNAPSHOT org.eclipse.cdt.core.native eclipse-plugin diff --git a/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/starter.exe b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/starter.exe index 2add84415895520472c801f0fdee626c1728dca7..61cd84a624d163f46058a9afae0430e3385af2d0 100755 GIT binary patch delta 18511 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 delta 18544 zcmaJ|3tUu1+ds3rgWwHN5R}^@AQu%ERK)wDpzAHs%*ab%ig`i2p_!VC0wofL9d*nr znU$3pg^G9AG|^W}Dog6sq_V<9Uo0!T^8KH4&hB#F@B4kHX6HZudFGjCo_XeScJZUj zffW}6%hq<MyREhMQ?ik4a#453o8BuO(i>`pSg_UeW&M;aoHa)K#NPG{DZ z5Bi|W2Ps+J%DTo50&4bHrF2L9q8Zcjrb$x1H!8A_NZKmjWu1~DjerY~Oi1ZS%^s^{ zvBob`n_e=YA|Hw5Cdh*fV_Am0-Vn`Z%7+Zm@#baTd@HsS3^BZ_!Yns zAE;?XT!~cdQ=eic#FsxNNd?I)FFV0uD>xf-<_H;CA1Pn(nB;MxGvEO^w#6XUTb|XT zht~%XPA&1Q&z8$u^a`z2O5SNj7rcx1!JKSci7Cp0=C+cMh79?q7Kw)Q8FClTzO0R$ zQ{OFn>AAD=MlwftoB}w&HvB-x4lPy^bb+H%1gU+KNxx3eK?lGxD2WA)dbkE3Hq; zm%XA4`7PyNy~5cEIk07L-@_9n=>(0q#G~K=^DerB{*Q!_2i8NQM*ap8re1=qt)$IC zWc3;Hyp~DUH&o_DWYr#u-@MW4RteV}_m4jM6!dR@lvGr6oRQ{>;xDK}hB%1Waw$ilnqf;P? z@ztM|A8XSu@TKllwIt#k&&BFtBtezq<+s}GV8QZ;wjqXpx>e3~_y1l-1vsjqM^> zf*jqh59=Ujw(G#Yk(ag`%I3;P+gXCPVhUBc-`gl1wMGX~)WO3tZ{LTR<$>+ZLD4R$ zXWddyq(Z7rUe-Pty54Oc#nR-f?I#938tv40sI^ODJCgO0ZGH*%M{TPc&U?WdrTZfD z$-u;RG)4TkLPS^%#XxD%HBa)^`(Ph?PGyUH(4<7ED0tv$kFb>}3|0lnm9}|%C^RK^ z(Z+sjZA;RriWE4k5KB2sYwxHe@9=Li+8=_Ln!(jY1E7|k+c6~ywr#PM`V|plE9IYC z(Wl9PnVHxM3r-PWs$9VX@X z`gR*?hM^;h9Y-lFj~Jye@=KEDmm*Jc8jVR_*r8*)R!-UseJZ`ZLq~gEf#xrZlSXZU z!}5P9KIjxp)`=$nAEN7=qE?71*1_fbexVh{UsLN;XWP-2r{Zl)0K83pfcxf0B6N#P z&H*SUVPnIj=)`P_m_%aLMH0HAEfUbv4Sh6NT~voNC=mLqiyDE*W017h1JjdQQbc-6 zN|jDa6>XR;KAlp0{^+mN0Suh-psA^#krg_YEOoZrq-$yOL|Ce=Q?=GL zN8x~``fyj%{;4H)wb%b@>+^rKy-#hw|4r*QFSoj=7wo0y_Lvd{BNR&tKOi^Q3LZ4& zS^gJ`rBcF&tfmQf*4b^F78k`p>Fu5<6Hpi7f2=s^>My8bDt)^CIXV*x z9L&ZXHl_-zZM>_bnb-tRx>V9|-p;4t+@@V)on}R+ zzoA^;$^+vIQw3J40=^JfMgpIcz>geytBY!Z>4AFMqim(=K(v7s)O*=VOR0K9@p;79 zDrcbB@>(i8^sQacpmq?fcF+M$se$UwAy)K~Lq&}(-IPv)M*P~;t!G0gYj$&CM}g;@>?GTZm8a<{53GE*x&6ncdJcj)~WtAw6S(cx;Li#(D?OsphOTDP9SH#u&v~#W8)!nyaW%HA_pTVC>4E5p#|I zX=;KaN0e+L>ut11ia#D*%Iy=->L^{AY4;0)6x9)qxaZuG;&kh7*Ggq!`s>JbD#^;w zrE)weGZ3j5ck2c0$*SQsaFc#I?QQN4gxQ_R0Bxp9H_^$c&f#=LZ*>u!kkBICO2wx- zKEo2MDjo^*Z?^!50>EZaho)*@*=k>ra1vLv&^1D-PbtO#>8`*ANp`9JbtMp8p1N>X z@zey(QzfOOlAJ=P#fahya9X?OKD%|t?X!FEpK^NS#pv8KZ-wHs_Bt|yNIM0n+he~d zg3c(-n~X||%%c=dsz;2UcR)?97;DJjMFr1C#$uCi^zYAC04pjv*RRLcA1xU9i z%L-1AQ|*#>;X}Cb-cDAf6IJOrbnM=La!BzS)VSEw_2t3fo`XuA{lk{iK&y*_p_(4r zM+mF?2(1j~5vH+roNNlM1dONB+|>jd3Dwcy3lufjNT^-G1JlyICCUZLw)*UOFqu=& zJYp;U4!3j*=DV+=1~L4E64z-DY$Zra505KVTDksO5ZdByf7UYfjC>|+1iK=)F{c^U zuaGyl8ZK`$MMR*8R5)z}RpXlJA-OSRzq% zyN~xF9!ww}z>h!_Kx+cQTBB68QJS0)zSuLoKRJ^p$)ARIW4QayFPWFh}5TtRwz05jXt_*OGrGpMhyN`^i5>4GiaI zYAM-paSox5`F*@|;kd(n&+2I__Ww?{bqP0o+gG03<;l+LGL;*)$IoZH!>m#@Uy8D_ zk{4oD%WO?icjWtBV%dB-G&-D3m95bMajO@R{*{sDCjVi8DaB`-{L=u6KWOrwM|Gv6 zBV&rsHTjpxtD}2*)`o&A_WxQw9-SKY{Nr$je1|Jj3|==$|HlidD;^5LgbTLf-aAlL&3}GElDtfkqnh6VB5UE1p8z5HX9$(j8UZDx zF zOu!rW?QPz8Nhl4OP51@xuzVOz246qfLva#hzy@HI)BZt<-H#C5vOBGim7Nev9FPo~OJ zglR*!c$O#!b??O5%Sqk4giEl~R?^#xve>iLybk`O$5x7YgcED!XS(OHZSqgu7qq-P z6|?#4=#r=?IVV2Ew;Dz7(iccGzFIKyWAfJcXm(M4KmH(_Cok(U!f?As<(VF*SwQ0? zF9jKStS5pCJ;}KD`>Cs}Qysei1icq2Q_genBmY>t| z{aU_L%hxM8+&Nc~xqloNk-Y?$1+A zO_h$Orhl~b=c&p=wtkHHRNfoWlXYyk*wi!-sT^q^(s86qNY^R{jvC4mYKE(JDaPR= zfByepuBd!>v^Q&)K0q(l*t7DJF+EJO)nt{~_%rsrSV^kQ$15B1N~C&V2lBRYl5`)K z@`sS<9gXsJNUeb>zlRhEO!?%lk`xI{d000|vH(+lx4R?_0H(Z04@@Ai75N>c39E7O zX$0`Xw|i4i;e$L4X$EjQ@yM{)o=hD*}Fkj}2b&ktX{IMI?2h#DqI(iK1W2Z@GDxtEDarXh$Vt={A>Nx?|z z^0bM|ynK0)uhEP3WtDd)wli+9w0>_=Oj~1}#kwKfzm-o<3=dCTqP23|tQxk#;!zns zC(OXCa!O7Q<|8l6na}FvuXB3vMhis6>aE-#Lb7F^50m7Sd1Fz#0iR{^*YkP+`{wrW zYU~9`JboL(1LUk+A5xP$mO13pxjmRgzLz_nmCMuSk7ee{cjrehX4c9tzFCuQXzU@T z_GD3p-+PF{o-CSK#lD{GiNOVG2MTW9yL-~`U=_Ny;xc`#j5wsb()$pp}j|6dV zt09E>3h!-(&g@~4xXmz#Z50c*89I!3J<+Nd*B(2_SJ;7~$%gVLRZ@z1TdNL5b(dpW zAr^%e*nOheI1k_AwfXrgr5J~(*=Fd^B++`iVYGErf~p`Dl6w`&@rDgnDQ2R^j|Cr- zsTC$s;YqEKjY3>r)t2ps%M62`wbO7Xj8%w zSTwXZjzl+o{EQK-K}_~Dc4uXx*v~kRT@t_f8IOk7X>E*()3A84lnj|O7c9zNoSi2z zuR8IGzY+7(t7>iseBN88!PotVwHXB%5TVrWbf$4(lDu@S;>%9z2v6O&IF<5{Ly zcgh&TV#QvRf>M)J-@S_)Pa+#u?PD=ggcCJ?1mWaFoqc(B#U_t z*clMG#y<)s9frdLuN}kfZ)m-t$8DmJtg&H>(jinZzAK`Oo60FP@ zH_#D#LHM6F4(M`2lUe~O>ttojhCG<%o21(DEZNadJayI>+HHl#(E!#dvKaOjO>okT*tCQi;)ylHlii!8v&QeM^h1LIA`991o< zjhiyC4eSUrWwH0fKVhbzjPnCj3->}n9JZV!%ee`e#Q*yw?(+!|c(>6%Nj z$#HO=Md~_Gt7~xbQfz@(Xf_4;y`_k4qh<_oU7Be; z>nN_LnG)K@TUBY#C~WT;B6yf7Eal6=D%U|$ANEpoXIwP?n~r!HZ0IdbI4hEbBlE#Y zV&yPXaL6W2wOSMUizXOOJ(Y@s!%VA~S@ari8qLOt)x%Ap*cHo>wcVi!Dki-tUa*-u ziSLJ-B3Zd;Wi#1AJ{@GGuB0)f2)&vS4hd$=v`vb=D;C(GsSUM?Vis}GW(pgbr8Njs znn}`!Xw-E-3=M{c&>327CKYCDg*hm6TcH)ufwBT((?sY9Q>bC#Bb*y@HglVmT zl~>h`GUbdnG!7LH?KG`4+#f0~?KH&&bxgG?{aFypU7%qFm7)tWaHvE6XI zMR>kqn$FTh&MT&_0kcx{7B3`=yAKxoUqKYTEY7`Rs=*wHJ&Mwg_m~pff1*t>jZsRZ zvDH;|c-3^6F>}@B*Gy5PF~h(7WEy~u5`Q)&AO>grYah1)!h^L3exaKPd>zm zJ*gpy#~IK=Kwo~3X2oj&f6oXzjt}OA42vKoh4-O5*YXse1joLc!o%ROkHNx4UPCx; zbD}RYx|hru!sBuNy)=a5HYmJ?^5MwF4du~j_%xOB#p$7FQ6}yUg_=6yo5};|q>fAF z6H#29%6qhQUJFf<*qzEdi)*Po80~*gg_?X3p2jojOkI=4m%@PG)A(Sl@xH_OSXfm& z3>{m<@59hlxkwq#GvUaWhbyLjF`SR>Sgtufl%@!e9}@k@>JTY59?-E)t4>oY@xq{0 zTf{;eI&g^7HW-mEZc$byd`BoF>q}X>m^Ol(FjTxaf)DHHe7U8s7wMsn4twF|UUhE- z|FS)tbZIIN>bqc;m1?D3!E|BA(@o1;N=BQr&dCjM*O`U+aUR58s~Ye)@6v_Uh=oNw z%y3*1KF{({QBlNA{2OR%RCw-*h7MIEmWiy*ng|;%HWcv)kyOMxh{Wf(nU_!xBpAUK zDDoaB!Bn&qHHAFX<4a(Rip5`O0~bRyNW?$O(=i8Rg4p>i?_j9Y8a!u!30i{(sDM)M z=XivnM&%41Mq#bcjPZ!T{i;l<=p;5j$2(yj--R$HkQDP=RHrM@P-qmnMF@-mYxx31 zgi?K*T33C%mIoom#XFmLM3qkoPh@C5W<9jX;>qXv<^J=g&Bm8?cw=izuSjMI2I7h2 zc%SR&Wa9I(m(jtU1r{TgjO<~|-YX(uBlj0uO8I!~GU0-EG-ScuCwM16=ihRXDwu%= z%REFy755XCcQ_Y!)^RT}aXm(KS}cSue)%4n95s-V(T$^{NZ-agZLpXE4w&#&Kqu7} zQYJ~Kz&s?bujgU*A&^Z01qDh^k~9v?5FJBi57jYq!K~9%ssmmQW*L58Rjh?9zEA^m zPbael%vzVs^ci^*7WJDpJ$rJH(@)dqFL-*we4Hi0PKFe{j%Ig5oQ%_#4sq}WK9`nn z8INdnA94_bqp}oFvRW}4ycqI44-q$Nc?+8RGVEH(l=T)fHgFreEZ*M0ha0S6!lxFK z-}oXQE;3)_BMjFi@zCdBD$3yJfLa73>JG4f#H%t7^Eir*&}P6JJk(IlMI!>a%QVdJ zY)o+@PBt|PoOW6jhAg`viSjpiAn8gG-U2pF5HD;*@Fp{1ejY*l$wq!nj9$-Mio=`u zAl6y@wh3W+6W#fUpv^oX@K?Zev$F>bSMtQXS+x*fwV8WHIds)gs7{BNI=fDje8gLu z;kp?jKp>9OMSsEn6wjBb{dN+Qw(v-nBDVX$#^YAT0qma~`nV706Dv zN+O_~&uvx6oS|q|LQ#b7#6V)6=k2_l%eq`#EQibg+0G-yk1t~c$A$N9a%g8Q65mF} z^4%EeuRB$jcexL(|1?R`lPoW1@!};5;-|yDX3uq)gy!0s4{SiuC!+bd{sd#zBIW!m zJSLzW29WO(aSozRwAh2$+M~wC9*T`1vHw-xLLAwHl~K`xHtr6>QOr$Mp|A35Oq|02 zMCj`nMO!iSb&R4c!aa(r{jc*>CgNW~b%F?Z1ECR$e#=CE!2Z1e&9DpqYrY-=rp{$l z=DcZnv$7X0YIHG9Gt0!LH(=&*!QMnromb7YzKNTRqlFmxCjUeH@fysU^%nXaElS@~ z;_zK$es#EV>Q`u8q$u0Lhl%)o5Ux|hw1L7jLTuf~%fwH6ozeCX<|T4AHavAE=FQH1 z@~O;O**Occ7cF*82>n5?sCbJ9WA6=|jRL-C{;wVzBgIE=^Evz`g$hMzpqRgp`%;i} z5G(id!y*-ii;Q<*&_?mhJMh}mP~;eVW8{_aX=VAdbT3>Zb5 zBd9GG2}dxXK>T!0o3*z;rc#Yp*emrHnMb+5Dik43p2XI)?>KyM{3xdC>|t%H28m6_ z;DfO+t=!`B!ECbB(%klyVCYMI_h?GMSQ45u<sm#kH#(hwa)b?-S&;ZbzM78-EgBnJ(Q@Ad8syNrdZQ|%Do+KIwB|CuToCZ2XsGd--(?B!d z2YQdtO+uFUfu1-6w4YENp>Ah@9zP58CZTJDV$K3h`T*!PLbZeDF zfW}t??Ict~D7YHvq4Pjn30)!-cphlv1)$A@&J*&x05t4hKra$HOUUP6KtnD9ttaFl z)cPXOpi4mO2pxB!ejkGKyaetrp=SvteFU`TL!bjLlz5rjHh%=F0zj-H6kh|h{4&r! zLJtVVee6Vg2`#Mw*X0wS`-JuYMHS%6>W<V+9k~4D5;+anoImeaAQMP4@9D`(3?`Pev;JmYng~xCtD%X~7pCN!Yh;g6cp)L@1+L=uJY`2*un0np6k$8lhT3k##^5zXsY( z=n5h8*FfXH0oqBZhEVV~Ko5Njw3W~$LV@1`jl2o8nb3Jcem8-JeFyX+p|ga1z5^Qa zJhi)UO`sSwe>ind*U(ZULJ<7OOlzI$pTPv{m?kihIz1iG^%iAqJM|=jvAEvD$dKW!?fCaky3R5o^p|d|G=>8@ zW&@bfI_4EH16&4W=FFcy7wR4Owb*@5RgjF%#EY%*Te;-w{^9Jrw58d(d53jYe}-la zF4bi9T`=_E*wftjH<(6DJZ#dK;5H;-#UJ=NnHVq*mrQ2nvYgCmxR5^d3vX*5ggT4M z4r)0Hj9JG_2jin%uGGm}4kiY&?z!6lW|^*4IT(E~9RQQz8e!&iydT@~f?TWf)kO%= z*As5l*TK|blGPzTHGOeTHojho(Y5*uGFgZl_n`goY;Z4Z7|#Ns(l3rs!!fn3iVDCNRlh=>Dhbd0kZgiluf&Tt#NDN4?cG0}zt_0h8tO z1u?C#@B)#$b%cPa(6vegb5<7-gTd@|>49?=O`o+$GV7f4s2xK0b%UA(MsM&kFeaVq zA~0pT?stH(>O6P=3_b3EJOyU7tFL+4^QJF&nwFZ*qE8?+MYoK80Q0~#4pR9On0)A^ zi?Zs|)|gJ(THLW70wx(#?+%tEFj+dIr}$v0W$D6q3553Ox?c~b(WM%0%$uKs>2Mi6 zZ(0skHbUIRkcn@jRl3U`nM21<$Q(04`F4d2R*gOl8M{?CvMZpL>6kh&`8wtv7z>oR zNB<`ndfbecFaChTw+DWS!e1OU}|-p-KJ)UIk$<-51r|{_XX3-)%|pBk(BG)5(^nKWZYXsPd^02 z7M-G02<7QwX&jgZI)mmA14Zryuo8?PitgE63noXWXA>CrlE5ES%+Af5X_v}$HdaEY zwJRnc&dJWEj>>f1e+Zd!onyZOLo@51-8&=$#yuT>fSIB*sD-~IJzAq1y+5e?y1DNH z=D5osXq5VaS*erB07H*^^ozvezY$!kP*J0^bSIcVU6*fxfoaVep8;b5AccJj4qNw>>V%%I!lwm1iO~=;@MB;PQ&h+(YyH_X((jMb=&)&jC}W zlUWXCZBp~StQ7wMP1^42esSKS-0AZcNH$$(ucO%&oqLah$u_z3sbDF+o>x8q7u=^A(s1on60xIj%Fph#%%6 zb&M|<{rgxLnDdIuXTt++G1w;j)=D+yVn{YkD$g&YM3&L>WDN z?Z2U-PG_?LKSY*6)V(mmz+`ztb+Lo;)2U7(#AwAwCqMX4kCX99LfZ({<{` zLnhrNLyf0_vACk;DfPOi{2{-4RXq!twJy(5tL