From 7781e797aaef5f5e64bc5665748a726de91de9c6 Mon Sep 17 00:00:00 2001 From: Godopu Date: Thu, 16 Jul 2026 23:11:37 +0900 Subject: [PATCH] fix(ui): implement async-signal-safe fork process layout and waitpid child zombie reaping for PTY --- .../test/incremental_kernel.Ly9AZGFydD0zLjA= | Bin 4028768 -> 4028768 bytes .../test/incremental_kernel.Ly9AZGFydD0zLjA= | Bin 4054320 -> 4057704 bytes .../packages/mam_pty/lib/src/pty_session.dart | 70 +++++++++++++----- .../mam_pty/test/pty_runtime_test.dart | 1 - 4 files changed, 51 insertions(+), 20 deletions(-) diff --git a/.agents/skills/multi-agent-mux-ui/packages/mam_core/.dart_tool/test/incremental_kernel.Ly9AZGFydD0zLjA= b/.agents/skills/multi-agent-mux-ui/packages/mam_core/.dart_tool/test/incremental_kernel.Ly9AZGFydD0zLjA= index df8f8a231127c1e8dc0ec95a222bb0018876496a..b60dfb09ce956f3919efaa45592d2e1af94c7b28 100644 GIT binary patch delta 182 zcmXxZHwwZ4069c)cQr~ F7(RoHJ+=S< delta 182 zcmXxZHwwZ406oW)%}?yW0D*>2X4(_Yq$e=HBO=5YN^Tiu=2+jA+159uQJ F%^!vcJ<9+9 diff --git a/.agents/skills/multi-agent-mux-ui/packages/mam_pty/.dart_tool/test/incremental_kernel.Ly9AZGFydD0zLjA= b/.agents/skills/multi-agent-mux-ui/packages/mam_pty/.dart_tool/test/incremental_kernel.Ly9AZGFydD0zLjA= index af0147cf91ed0093907305b2cff044ce42f98ec4..73440f4ce34d3cabc7e61d7e23fdec7a10e95781 100644 GIT binary patch delta 17895 zcmbU}2|yG_wpBe0BB-FYf{Hjm6i^w#3p~L4KqKC`3Mi2kS=lrXvWz+_7$XAL%C61M7CV3pX4L^~Jgt58F^btb3;~ zy`o`IJta5l6)}Gt$brdLLlE02vPYUg306)#hWLIM=5qD$cY;5o?@GEo`FTq zuyV#U<1--N7?5w7Tt4U)#gogICdrr9h1y6-Jm|NJ$I-}PTfY#I5XkogLR7xAZsbdo z68cUdkDi2Y?YTGBF%z!5TPEv z(6%BD^>`I7{*91J6toIZd2ePSHtshbYWV_%!Qu#ETIm!%4PoP3#>+Td@GGZD)8YQ6 z@gAN8_j{4kSmL0!+$uNo~3m3D!-cGKzZ|Ik}kj;P5un9%G7&iN}-LITLTpb}_wzC*Lx? zVtlrzX$>Y?3g5$d4mP!$el8dUPB;xZ6sF$`U`rQ1@eI*9WWWmwFzf*Z{h?uX0Z1$p zcov#2hb9K(yZ{&Y6ol6v0#;|hW``675w(Y4S9D^Sf;n(MlL}R^7OrNATHA}50vgn2 zC*Zwc7-n4140m(lG0BCD1)_u43v}{exhB#ES|~VGdnhQn;6lMWNI4fY3+X^X8!>@v z1r*$whoTF9FLXtma=zWc@G`_i17at)35G*QWAk7xUNVkb`7jXrJ2;{pRU3j$cHKbf>$Lo+|*%ReB<&Z-z#y3mO$g(wJR9m)rXFe|$V z!`UF{2GCLTn0eWT1B#}s=w2!bf|^;8WM+f4D5evAh%3|}?XL4D3N85ujI0(-uINwlr4srBiZrWe zvJd)^dkq~EWT9+<%Xn+iYLNy~DvF>}{LmE>*cP&>qIla%0CT^=^026Qp)2rMSyYFV zYr66%)Ey#^oKT5LOj^2O^6fQ`tKH5cgdvH?IEhDRMG=in!lw(5%?=)m8$rRq1YxVH!S*B$J@mC_#|ZF08^9wpdj1CDgjI+i#)T70l`zyDB(TvIvT3fIZm@ zMHl-O2O?!+H$h;%%&fp-Xn`jRUp!JSylp6;cxB?_QcI&$+Tt;yv>b%w4R(6SML`E( z=#L{Zi%Q>;WGNnFmj#tBhN>UN_V)%+l8e)ja-&pJ3n9j_qDgjXApXJ@M#XVRlp&W$ zHX2Y|v+;4E8~}n`Iig%DE!rffje07IVaTz9!g@je@dwLS*5EE*zOq(0k)X?0oZ}F= z%o~=NMP+;YfXIi6Uq;H!4&xD}6e3_JgWh5nAN=2Dik*OMi~DLPRZtL!S6v_jif?W1 zMlIa}3o1G#s>n}^lAlCB7P%^l0nVW>2_5Z12{I038@9~y%ijTAIV`{YGl;%|>P|US zS3U?#h+|Q?#T|6_bMbFTnIasRQ12JX!I_CH4r~?43aN)euo&5yljIHmmMiRWpn#H* zDV=o1b&rkesRWKSXmoo@i&DGc3%MyM1f*}mS%j3mQ0+*jg|AOy`U6g4wKi!$WXV^J?f35>z06hEYSG7Z?XIu=#_ z)(`woka3|y#>!{FbYSpWUy!k-FcS}PG;J5*^rQsBnh=US*P&!8lpGg9~8WdSNzw{^* z0drQerAtaD_kzk0X2o=#6%kUp84WAlMmT|9X-+n!cigx1vPbDIk?xZCt zfg}Sm4v{U=Oj;0%F3&G7M9N)|DA=napYmeTifuL0gz}fmTcNyBB1h%K?ZvmtTTN;H zg00+azBC9us7$52>|`sqo2L#GZ3uGdM23@W zC|)q3%9_enkS~{(-42yk{)L>h$pt!o0Ht^3o4E3F<@?BqYM*?&$DhwrU|oCwQZvNx32cXSxIDRvXUUY*mKM z6dqOyz5w-?XbV17MPf9G#}BG%!1Al!s=5Tio2Y*G;i~u9s&|UMfzk#(VyzKX^(p1# zOSbBIU5Kdj2UYEMMg@IGR(0@BJs=EK{lHdzYYRhFKib2P_^^j+tJ*cC8WIL-#RXJd z)$ZmY0|cc?>aUL@e-ZRrJtC!gm>hBxwJAzi4jENF*|$2%y*i4mjx@)5iZfTIRKsDl zgT`78hHTTCyP}vT@U=6gdb@niKB~^HptOLEuC4{wN2Czq)EPTcaO3J)wz^g@grZJE z1Dt(218={=6l@TTCGMcc|_KvlUH@e~-V9BYgPJ$OW()3jf7J{wASEsQ?MJ zaxD2DI6|Z>|HSe?RH)q%JlSFSpD9W%%#6;V6@7fntZ4r0@B_1oP6S(|EQrdbi7+5A zhp^_+Wlp`RM65ZKB6wh)OxYHJC8+tVdA1!Yib6d!FMA9sfi=gKaW-U$6zq|iX2+e8 z?Pkq6HpemVu{(~aA9EqdYc{jyQaYVff&w0yYXOH{K^IY^*qg^DnIVZ*sShucufc(O_CWx)^GjpAG16d4XYo<*Os8ZXPt?k==RGCvNE){^F#v|PY zm0A@9mD*mA|96fmwJK>wr>Ih^s+}rCmD({WweWn`9zbiyH@Q3>RTk9F!ozA;E{A8t zig31e3pLtFY^{!_RFm1-1{znKpT@PvYL9c4>)@usBLYS38^R6sTX+nMBWo{Mt~*87 zepLIZ{Q$l8Tk!zB_6JD5>U!3>L$s+9ebwQpU>%O54pJ@JjlIsa!$F;xfH^P{)K=HG z>7e6S9X!ADI|DeNZZhFTuach?J_bmOvpU#{XxTav*38@uYjEsNL8Q7B&fmpjcj!ov zSfhhz8%QB5+w6twZPc7=FH<{EbBX=t4r;C!s=2y>wrZ{&HQhnCP;*>#-J-e`psN~@ z1i2(;eRVOg|4VrzT!_74bzAf_HKbAi6Qk_WyCczoUS zjH2#&%O@ZYRHSwL;hWUL(A&}q*B$08R~1opukJu~C)IT)r$Xo>WHySdd$Yc;g6_U` zAK$KfuO*YzQJp|Ek0b93J9*uADRp-NSjrY|)&1D~eOFIgP_KY;re0M)5+n!Lrg=<# zXnXzWrniJg`}Jeh_1sum-Ac3{9>kahQGc-hw5Y9mcs_*)O>b>xu%P}W>{I_5`4CimtNx|t@9)%~e9j`~n)RRUK=l{Y z^%uH4{1Q^nJM}l76HXN*+HvFximLyCGS2UQL7(Ro;OcP#s!A0B4ObrVKygOL`KrBw((mTI-7I?-kfOVG4P z%W=#5;?Oy@<(zB?IWNMNHp?9=$ccy*{!v)I7H+^6EstntV>~B57M1ML@-OSo9#IXD zvNb5x4N99iE@YPO8`ke1^@o9|p$H@qbn|}(qK3_mK-AI=YY>PUHbeaB<^)YLaXR+IK-7U+ zon^77)!lw`7qxl|fv91#EfC#8`;*XZwEsqQ!~TZDpetJ-;-pB_a8z_=C}812?1WXg z(AIGN`Cn}H?|&1N<}_Tv4L2HYB3r50&_-il!<~+X+pV`U#g|ab>tM)1tv$$92raj*xHY}Q>LSdt_HDEFe*PC)D0W!; zwcZlv(b%zvoj zf?BtvSQ8zQ^0swbYdYmYTw_j5N}Qvyb)QvhrLl)R2mdInMZyiZiWN!^M4qST6ym;Y zt+k#OJkHvvwl)&07!RxmQ>^=e&L?WJA9~uXFC7>v$_fw2$*1IVDJ2wMLx@|1oEKy3 zIV<;8(@2UQ&V_*HJHib-1PTJ@zI%(qwaMH%eMmVqSdcw`o%wFcCFLZIz1g7g5_pQdc2QGE?(at~t zjoUk)aoat<6CBMI8W)29!8S|JxXD4$M}Z&7{iw)T(I_0~{#S?GchC#XGOv8$p#A0^ zdf^qpMY%@%(eG{a0)slx3p=A5a~tVabx7pHPs|k>i(nbAjiEx(haHG8jl|+9V3ii8rJyMczFIP0GyKmg4!EDI#8!Z zP%kvzz1`S;;I`lwjrY`z_e8%4Yy1HUHWnmFcv)Ehb}lX^pwcS_R$ zQ4o5{(7`qN9&~fK1NDX*$ax8F8q+kssmZn88r z+wHgMglNA_e*yb#`nc&@_s=HDVVTjw;@BVMwKd&1q;r_6Z786*hyCFst-qx`NgAeh z+0-tYr5Bjx5n;EXngnB{141rGzr@6q4nVSw9Pf+VMu$fV#?{nri~sHD&`Xer9(ILw zZ64g-Jm3%{8?enbb3@e4L&Sv@g9RlN-5lCH5e)FCycU)@>5DRXA!DTS!k=KKZO!3w zk!7O+%`d_cYS*n3p8weqP|2GkM9Ebk`7t?pc+Z56ftU>A5FV~z^9BXjwP1e;*MW`< zxBJ^2bVMzvq&dQ-63|8?y3L^@^pw8&{H^9Qhx5Q0Kqs%On_s7|Q_VnO&F{Jc%fKR4 z3;ad51h#~LW?qu-=O8>ClPTzBnS#I#q-v&q?BPjtcN zwuIUAdK(=%3t{Z&#ORi1S~Q@mS0%Z`FxH}zg|XF`6KWjyCxo)qG?eYbEiJcO>W^53 zNYwJ2y5%`>bvjy(9KH0gKxlq^MUX)$Q5X}Orva$Xi|S}q^GL=`IXBZiup2=%;z zkn3oKe02y7{{miA#?Z168V!f7A*rC29#l8r&_hOAM(z5fQ?s zVWy>xU#i6e_~}=ByYuT_7(L*`-B5OA50C6!8A%(HHmTMHk-U+AcP#5S4=zTl zHf>5)FG){M%TCIiO0T2Rvd4{$RApr+X6Iyy!$OxTJtI3gJuNF}ifb2a{Iqa(FrU7J zRSF3H02xq`p>g2Zuw`R%Cck$AJGQSJz1TfHoE^ZM!q|aM8Hw3jPJ~Tj*EzeZ;Ikk(sk0J0~+KOO>9c%HEQs+LDx*p<17` zDIMm+KU)KX=$9%nYggKa;H>1$z*TTo;-;kRU8=y>TPLc+f?WB)+3Z+;++0>YS>*Z| zm^V8)b4hllDndnXlG8TBebR>P^vqq;)Y<9LiP_0Jl2&GK3J(O%DdVpEy1DFVzGyBx zjel=08xSJ&is)<{Z=8|2ISVj$S_q0HGBP%vZ+sfosoy--i$C(K%2|<-oymvIV|^xw z_*JS-Sk#FdHwFTTL>)#mH}8l|R*h1H#sh^6{>EH(5VOyf&z#3jaRRN5=jYF2<9T>! z;mvImP^mX%CM5+X?MwnO?P!uWsRCuv`$nkJa#B-+U?r&5#VL+)`!xA5<-|TfRUas7 zAw!j%CJ51suAZQaAk`lJ#VB@wTZVnYKE7cVn>8wMd3I*Mq|P-eWfF$FHBwj^mHbX2%X&PPH`n$y)labo2xbb*CRuJ%hnkKtF;RsXFODga2@xV!(-^^VwXNwbWylN6lL? zXW1fH_s|J;H(EyhV8fQ=)Qzg$>D$&PC#fEk#WvK$w($j+1!*WuyR;`L&Jby;? zJUTf@X0u`_;@jr4gE%QH3BGH)mb_QGrT$C3KwN1tI*HyxS1NsjEOyx(Mw%HYu(*WA zI{UQIz>0`Zn9Y9|&ARj#BA(4u_qpzK)ePkiEn&wfQ)2O~>HIagRLsLedAFtPklE|h z>PgDLX#vX6kz;&DI#0wyz50844+$F-;N>#G8MDhg@T5WgT<~P<<>iGv2YI<*)o2$S z?BR@u4<0nZbNE1K%&%I?M!N;#sf$Mq_jY3NQ~cEH5l^jkB3}|MX(zWKupdV#v~;W! zIgVTs5ku}Eau++16K?QhgdVV~+;gHI7jhrQzE+ZNun46fcb%QcYvPRyOmW!?`@{nT zQ)2m1%h;hfmX8v@HZNm+;4T-wxY&XHyZt!9qgUiYzNN3JNNE=N+dvWf0CLyUF(mG4 z@MK>$JV+dd>}YkT{vl$&?PNcJ;b_*;31p}QA`kB9Cj1ROx zXrrLPWF{QibZGEOJClGA8cQA`ate{t4EYQH&I)!srx>d6Q4CY47+*hf#y`kk?LWpp z#6Q%3od0-`L?y*hF$JEIe#d*yJ#Bddie3Qzw!$ zk>Qb(A}2?Z(=(^coEkZ8BKhlFa(W(&oR69jMNTh_j3U-3@>~>YjY^zI&MqaVmqj4* zI)}&`2p(FJw-C7y0}tuQ#Wmzo40$_-yc0v-jUks~$a`zZ`!VE$_2ldZw1#}RfxNki ze1yoAE#%`(~S(#e?&^5*uD+efbO3i2 z0G>yR;i?3_OUb=$uhv;L- z&*Wtoeud~#$v@VRU&slV{~Fp&jN};fpC$!s$UoPRf04h!)U%`r{yh)>6~p%#@&+kg z1vhVzUr7b2$RU+6%ck(s|NZuj;UIUcg27vcS9eGWIQ#H&!xci70Q#FcIjnhhv za*M{9d;)!+k^SUFO%HMnuCJ2<@=@Yepmr0H%kb5PNE^9GZfRT+$vM)Y=?Tqsjm9lT z(~I1Pp06~$q4kN;xRY<;_B)NoT9|hZ)N+yhUDFo`oFhL1vkx@X$`RDWj(0$0zvqC+ z2agjlyqhz4y8wrtx(MIBAZMNd-=5IG84%X6yk!+ThV$2iXu>tKGz&CwniS1WO|GU? z!)sbJ2Q()%uW2r5KG%Gyxv%*_i?ockuhw5XK|57DR~xNerCq1Z(C*Ui*5+x8v=v&j zwpn{nds=%z`?mIq_NMkL?f2S$>3Zngbp3QgbwRpN-BjIt-D2Gu-6ma%E=Q-)<>|_G z4V>Idrm^kekn^x^v1`lb41`sMna`UCoF z`dfy+h5-gIgO9<_Fv>925N?=hSZG*kSZRnitTk*lWE*k}I}Ljb&lO;wc+lGvt-$)#Nqh z9n3qCcQ)@r-nG0h^X}(;llNoZPx(x~bAGSN|6Bmal|UyR7e7<(H%jUmSQ#;1+3#x2HFW45u} zc+7atc*%I(c;EPU<3EhQny|^))W!*(Qz2U@A0~ni@?nn2woF zn$DUonm#rCye)Ctx{T~yP|mE&NY6?>(Y%^<#lvmI&$6|D z8}+gLuWQ+1yw5uLXXiS$55I678_bQDGdMmgd3TZw#{~J{gssV`sj|U|^1+Ex(j*%X zlaGhlQ>Y!=CT~ni%1GT6oV;yY&WZQdu^%u)W{8zjdZttaN?&_p<0JU?(@q0=MM1Td zxIQ&0X=idae|bIBBM;ZJcf(M~OYj5xWu@)?{vS8)(q1GA*FLXGgRpI(To~~=oKAWpjnEPkWZ-a zFwJs5%22c>Q?mmpUE&#k$U>e1z~S`3LZjP(G<(}LJ4r#$cxHrcC=j{AD|q8Mjfqic zOq#QR08Z*P1@P@A&6bWTHD#K=3WxQY##@>i@?kIWv|e*CMFXexLAW>E-`2dO36PFJ zY_$6%;E|BGdBed3P5p3i+!%!2$7?Pr6q-v~$}xO6@iQ0;^jEMZ}F2h&tg!`g)%rbDW|dCG4Jv0d@ZbJPww?u8;{R zTH8-M2q{^>g~w@!(5Ls>u{)4kbK;R%nJ3WC3SJ;ns!m%e{-3o_k z-om=V_hj+msdn9MZ7jLtB{52|#7z}WZnfLnwA+aIyF)mqjf;SjC#`NegP0DjN!ye2 z(U#8wQUTgJSaKLTHb)d)`)Ppo#NZ*)Ofrt6D8;lxGeh{Q= z!e^>dJhWCXvS=yn_K6JfsilzX*`2Tq? zBDmi|BrcG4wpI^zu6=qD@BDtmNU!CBJ1A-ZF}z|&KMGhHMGZgy{fKHt`}fW#NgjN| zuf1JPs6U8!g>mvm13dYAA4U9Gv3TinKK_#kALo@ZYhsqhoH%|Z;w?rk-i*mk%F0&L z5KD2NfZX}6Gt?152*=R0_+0RXb1vZsujUVY65$J9?*Jao-QQ!V+h`QrU(Nat7=uDQ zL%qfh3K=}kbG+Mxp<{iJ=R{SQFLDd_oa8y#Z3;Ugpl7eCo)JO*qk4Nrs{GZx)P0Bg zhkAHU8{t3Rb?AtR13ahq^Pe=(-+zkNfI(nX^6pXV3BWpX)t$2%3xL zMa^H}|8!J%SoAU!9kOIWaM&^wG<-$i%7x*>SB3oPX+b*(G#ey2vSee>zX-IySRBW~ zGc#BF|schpui@CRpuw)7GP;u H?Mwa_yz&gz delta 14745 zcmb7L2|yHA(yrIT0E!3ds3|d{YW*8K+yRFaZen(Y(^{VRCd)?kT z`!jj{(9eV#h=DUG3|70J8w*1Iz}zdU_GMT>+56k#uej{#6p%=;eG)N#|0$ zi8es#(e6XEN!}jqzC`;MACLAnMEh4?kM_0#(cWm|>X63GLq7BUh^~KIS0`s(JEF_> zV|5Bikf-G81^CdO=+3oswlI<0Eh!y{en5NH0@$r1(a-AOd`R&p`i&i>2LYQp5&et) zuBOgJf4mcW;GCQ#esj7IL!Ztqs~IyDF|6srs-61jN(?WloX@Pi8!?>eDh-p#;J@98 zF%UJ546r?2z`~^j5aXQgQk|12`)TIigBbr2@Yv>*o+K}-2Ww`!kw>9oQt@vf$t&sU zZ1GSGa_mL&8UwLKcyv&2Vw%va)j=GmCZ-Zojd{KfdUM&Z082WT<^zcSX*3swau5Mi z4WNaf(KxSkP7OfDkT%$hRVibnKA@KR2ml<%VYLo|(zy)QK?lJoARuMeKv>KH*8sYc zjiCDil!IjgAp|98BQsJc*sl)yq;r`vjZldOs|$OW+A|7JG=RQSBj^K#tDp~u_TIrr z^StRY0SM=^O^4FCrEM8?1j4ErNxURNWC{?q>3lYdv>wMqL*HZ+d?jqa4m}|(f&h{0 z`(b^`DyB$O&uaXe1K=Gg^FhQiAK?*3gb>qtCU<{{T`DS1=C~Hc{+~HEn9l1jf_DhA zePC7~yhw!C*bGlluzCqy3w#fp_#QljFWiX_>s!S)KxTya9%AI;!{9w=h9|i3J#gat z-#9jy9vI#N?>+>~Vdf~rH-O7F`!?fKueyaoVxRbU*(;HF%I(Gg zEg@|z{^T#Lw~zNYVi7I-ET5taj=~Cs<$&c=)`C|WCp61XrdaB60kC|Gr9RqHACGy2 z8|)YmMtk(8TJWAkEN3m>R-Z;ed8DPV+^ar~3!)dtS$@Ok1coRdQwkU(D{KRB`7EG~ zO(z@BD6AxZ9zKmrBUFb8#RmK<)uwS&k5d)P3aTJ~b@l0{Cy`{}(9J92qlAa$$$Xg#Tmr*kT#$x^eJoy%30D*Bc&PNY}VW9A85_W*DWkWdki{nHa>*z-g`C$cWbs(kunLNc z{ZPoN!WvM{_uPH4b-h`o(#FpzZOa{+Y&C_oo^n6bBckwqVg92KTK19@zD)+B*1>{@ zWdR>WAvU}AEs*H89IV4lmuJ{gxWbkSN`&?RyjqaM7(N%`Zj{+o;WiIde1m&jY@6Q> zRdJ#4OHih{ow8X6PkWdZM!@EXT-e|V-qjRQ4I{-8A{1_xGBfBN$o*X6jT%j%5=8nmG`?XrZmF?4lZE~4*r#=v#75p zB9GRHqNH>;C^x3&4h&WiW;)CygLSaTx!vXjW=_yX!P=UqP?|M-e*E;6C17gQJey^c z@xXx1UeSPN$fbvIid9h7s{=w_RFnnE#m&YegPbRz+UK``zr+(hyT=aB&T?OuDwelU zMe98yimZ!UQA=}YmZ?ZAP{optR?9l-ql3&xgmuaaZ52h>tyx`8608bR*@L@6QX~sS z9+qFe9ChVVouGp94S2pH>27ti?#kXq8^SieBkFEn(SA@qBb{fk>5{4Ak%mVcSSquX zQV)e>F&;-kPTM)?sW4|J!A)!qi70A#=22xmLQPWBAz4jfI#||!#BXpuN_kw0jPhZK(n zCCh`!7E+vey*MF%7A8x$juub*v3N>0-p3bf44Cx_>@b2Um6kd;V(cNYcp>Y%LRGxD z;tzjVj{WZyuatFzCl{M(86*_1DLzQ}nBt8PR4mX+>=IFIS^;Aciw}nspY|_4jhsKc zQGB$ZJ2t6`KVpPr3XH?O;&W1D5i%ILDkOKIWDLjSnCq(IhLVfzaF>IlZnPYQ?0!ae z4`g;F%4d;X$)u2yH2;#cEuQQPKd)Rr2)BNA;H6R+U^W-03R`T=Gv33eG->CBOQY zdaFtvRL$)K>e8-MB&c(0CHG20Kxh`L1`iC$_2@q5| zMV6{Gc{NH^T3xyoltWpzuP%LyI#35Vfu(y?rP~?THEf$k>zMv=cf$Og*3lOLG-X0S zSuarL;0o&AE~v}Y^hJW9Q`$TXEgN5kyFQ%~Jhv3r%Hs1ogqDr(SQf7;i?5#C1$vex z(U;_Vmg2andE5irbCqSP$}*}$yTDqMF``UZkt-Pm$-w;!-7R<7qAJ_i+{Li2MGsBc zp|W>DxgIrv+Alk%Dmz+KfN2e0a-NY`c7pLat1A1f`kYEO-m>!&4R-7%8E@JDl@DNw zE)#C3${JmoF1z`#rptbTpt3(?O_zH=hvrru>t8-nRX&W7zE{pSPaoQF`Pgb+g;dLP zRpl#-qcM$f3#BPHmKT9i+5<7|6Lqk-Q~t|(?NL?ia`)QHdfl%$_(-q!R24_uy^gV7KUSP<(Mw>& zuBa+5xNM-}%a%5fSn(ax&Tp!Udu;q>g#Tm31EhgYBw5oNkWdMg!2}6ac2rfibrGuc zXZ_`lOz<&@mHk616FOEVT&;}C$3c@Tw-8Spmu|E;l9W z%B{>$NJC|n7&i*$?WAkfYHVj+*Qlgh3GDrc*-f%MVOb zsw$BUavQ;h=ini1QvSz6G4egx%=cp#-wUd$Q?A*$Uv<%wue$1v>`?Pj6F(z`Eu`94 zRn3)Eb#O+FYJXLAo5$)?Ro%ySTaaE9xk87B;h;)*b@d>ZzgNfoSUvP%f1gsFMS`lI zPr~;Fia1quG4q_Es_K_nJR7E}KE`6C_miahi|WfY>=Z{jX;W0+mL6E_NX7jxNvQt1 zhInbJf2n@pK8q4N%V$wycRY&{2Z=+`tc`NSkPV4tf6NBl$5J#;7T%o!y8E#gUy`{u zi1D>sn@^}%VwWaJ?%;eqMk2&?YLa#Ad0Hj)^z6t|KykF30`}7ZHMb%fo?x*qt>l1C z$ygf*S%{*w9Pk=Ao_A+}P2e!NAFhL=Ov?Vm(XQ;T5o#~ORdCGIh-<}7s4I)igC3TE zXN#NN{*O0uWxQBy04gvSXK(FN`nzrGu|CYkN)9Y;rAIJ6XN#|4)zJZQ;&DzP9=H9D zfN*yxp1@z4k4^8eDaIKV&)9xbB#M{TgZNdn_|mH4k~;{Cd% zw1DXZ*S1vp4=EL}cFDH3LqhTjcGVi-XkubI(c${F52jfAV*+HIWSxPy3ze zYjW)&=>?f}UbJ-{ONB=APAn}n=)3ye+~*Y)s;9LZs~+r?HK+jYYXjnD*2* z9sL*yvXM*GwmGsR+MXH@=sIj89%0)^OJp+6bcXF5ky%+E+tv`9-QQ-vZmZhb^=Dh1 zv?^rC89s#AUiP=WeBJiq)~@lky?$~VE?rXkZ+qQ#QaY2j9gemgPIH;TG#Ha$yKMVW zZn_a|yW!CU-if5fyT;Fsi7l}G3n*&*r3W;^nm|@r=9~$q9oB@{>wFSxBGyCAfasb5 zXomtb#3?ny(1dE9teNf(KsAeG+%-!v0M!UJd8nT9RxHCK097!P!E~1$K0XpLBtLAd zF>ecK8GxGipHi5LsM(J|B-Q-K08~@d9DpiY5e)+n>+|xwLQqB7AM{x&0Iy5!l4; zr1jk%=n{2IbvJc;WN*>2T2CnqD zAlqkNwNKp^D+MBZajr6Ty2bvEQ)Yam-*mtrE{4 zqzC-8!~PSiv>_U(#XCIztYP=^I#KKGnBkjP+ipG7`bXFLJJ*RRwSnlKwNbUPZuhL6 zEW2mzG<46}CAHcA>3oRVAM(z0PC6h$)5FDIK2p0{yJE-dE#1@E%h@TSR{U=dh-&do zDz2*w!Z16im7TN21fp}YE{Oj>9uc{gh6H>W>N*m-4m&L#{ zqkXiaz3dh7j_$ZoRG}?8!kQdGJMXsY8)$gU7g}hO`GVt#Y{w`G2;1y7IVSJC+tL?4 z2k&XbF~{*#-LI&4wvH$q3kB%`?_~pYEUNp}H_@?dJvdfGJ65<1(1AOD1n$sBJM_c3 z{*ICf(t_;RgZ*sL4%vvhg~ujt4>G_!ll;t)A=C zIuDy=ORvjN8|t`S%bE?<)f7<|)qJq;UW%NpEM=|pk&P11_2~=JA|vg;(H22&!rtsT5@HQXaOG{@%-P4|sJz68`&eN?j6VD~Hxrc;&v5Xv#{^@oP_9+6sqpib6 zaDH|M4;|H_*flC)Fh3cjkSDm%!U|t z#l^(*uiy6?zg{68Imj;%H^0vJ5SO3fJBwZF`Eeqx=R-vOe!ib*tLI0FJ^#x063^E2 zab1zw?8Kz;v)t5%#>Gq&$y0So2dHwlb8{`dUW6bc;)An%Seh3-`xkniUcgB@iC@9(iuR%}f^Qnm)J33|h!@@A zho5ixVC1^&#V%iZ1>3$-(gq^;QqW7@UUaAY;EO|im*PC%100efTHoh;3n|^&w|a3u zOP#uPZ1v*e!JEy|77IV(;{>j^n!XYg z9uyfgAZTDvRM4QHn4rNyv1+=fe|Z1M{sa0CRMWlD5Uq|5;fBQ0eM91g3>`9T2;ChY zA3r>nzA`dy2A#kpsxX*_2QP73U314pG*$`Jvf*CHJR2Y)3=i8+sX7$GX2|JdN`TB^EBPN5a!Z% z7t%Kt(IY^QE}?&4ME{XY-%F;iE~9T`(PPQ<{pIwP74(f~`##%mF8yFNeRWMl7X5H8 z{V0omoJ(I_A3c|TGJ_u9NKb4+S|>B;-YqbLp4uqTS127lmwq~fewIu>rv}VKjq{V~ zX}o)tnkNB0L-X;j0DlYV*(`c41)oZ?*DRlf{#Z`;(h68ZznF)^s_BJf`hWAV*+#zr zdXd`kww7MP-^Z()zOsdgE?l}vBXp#P-rApLjg zow@XDynU7aofgcc-_ZB4_89$k8U1b}R^nGD%joyZ=npdmdUpxEM~`FWNh%`Y`}9-1 z|7;WeFl{NKJA?YhpL0OZ(S!60`ePd1NB@uhgyrYC^p|A%E5h1`u>OVRw`BS|ZN$f` z^Z^drhoT=uvHw8w`%u)^=`D(eiC6R2YoWMsp&0|g+Mu_kMhNSVzkXP7O#-4NqU|_8 zNC?)(YR76d+Enc`+Gn*JwSu-tTdb|szNS5>eOLRT_Pq9j_NMk%ou96=u9q%M7o{7j zo1{z9&CsRk7VENfD|H)mT3wm0R<~96vhINHi0*ye=ejGpM%^vlJ>9?cKKjmjwLV-Q zqaUpwtDmY*(WmK`>2viP^m=`XzCzGj^)KpQ)9=^6tN%p*nf{Xgrv7XFFZe$r9 zW5_U+8)^(68%`QNGn_YEG+Z;>FmlE=Mt`Hq*wYwj3^7I;V~lae(MH}l$vD|K%{b4P zYRodOGUggL8TCf9vA|ertTNh+FBtb2-!i^u{J?m^c-na0c+q&nDBLstoTte1&r{_E z=SAg>&6}OKB=5PrioE)~qj?|YeU^76uPN{Ayq`>*sjaD#Dclrk8e$q|;!WdB(@ir? zDW){jVpEpsc~icr!nDn_%k-w{Z>D!mpO{XWPMa>6Zkg_yelq=T`nOqW?qUux4>FH7 zPcTn4PdCpqFTzhUE2fx5^GoLa=6drH^A+>&7C%czOMoTF($6x|GR88&GR-pEl3~fR zY_Jqt>MXk~uUn2-PFOy(d||m{xnud!@_W8le%t&m`F--As6Tj;??LK+ImLg^ahper z?O*4^#i-N#0WNEam~n>h)oXP|?y?!VIcryBtk0aZayCXKWNye5@1N%T zg=Q^I&dgX6`ph#~vvHZu%pE*9$N4;d#j3UIaxw=G7WbXugA^G{mWU_trb8_2>}re^ ze?7xTiFeNM9lX|NZORk_&+_xvO$!tjb!6d64sG^MW*9eB%qgXZwYdb5=c6S%=lmlMfZ?$e>8sfHP$#>^RX{;hBRwwS5uL<3Jd$~hNU}}04zPQ z^u!W~r5BdoSkzd8umocX!O{myD3&lR;aK`&iNMkiOMfhpSO#Djh$RY3G?qbFVz3Ox z5{qRBmN+a!u?)i!k7YQP5m-iI8HHtZeUUe>TZ+3v+>@YVqbuV(EL@7B@Vj4p!v}z$ zWgv9?)WCTWZv~!z(;_|gmbMQHTE_0BOFI0em3o55C)C;*^WX^T;Ns{xqM+w=e{d{H zu#nP)Scw(WZ2G0{K^qPIr$E2OFWS<%u4D-PUackF*+{LAms;Dg7dt`fO(L}ZN*t=u z4%UtWrFRuh2bGdICkvIb{E>J z^`I?o(B{+1HfdZ0!M6fZTYqSaZ?fXFwVVQ@)#pe6cSu?X{`xsbJGYJ67qy>B$0pi0 zuWI+ui|yod6YV?M+PBiVNYWmkuW65IW1Jgn7w-<~WB{f>y-~YtJ4T{YV}Nvw(+Zaq z3hgBwz7>`(NsZbsb)94$-#2P+&?Ejb4;@_9{z@-mrod=0VuPg@a470>NfD_-B&J>@ zgT4HdaHT3bGsYb=2=02jq?0(D0=Ghjfkr2U=>~vO#WXrZ7lj(qO;`^)zEL-X9_h-a z3tNUmH#D|az%^ma@2uACn1HMzbo+41vE{u(KR<_v5v?%mbRw|@B*44TT`(6xJKF|>i-t(cKKTRhdktGy>ooiuym^!mFE{QF$A z{4gjtb8T+)l8l^Oq^~%Ndq2(_v+qbCDJ-u%8uh_Z-w{Bb60cw5L-5C^iG5i(&_A?O zZ@(yrRt@SJ+ARhK2gLRm(sOWNT)d;vKfUyywL))tR#&-=E*Cljhx3JLB0o{7Q6JtWhj)w_PgpQvW z5IS*E@6gG;CI{mG7kqL`;?&UTQ$}cpCqdHSnNy>O&w|MCIsN8N8xcNl@cij$qLEH_ zby^Z)(x7Y2lXXY-F^o7j!T8HQp}>0}N#ajU{KOiT>ated>H5Fp=t5& buf, int count); typedef _write_c = ffi.IntPtr Function(ffi.Int32 fd, ffi.Pointer buf, ffi.IntPtr count); typedef _write_dart = int Function(int fd, ffi.Pointer buf, int count); +typedef _waitpid_c = ffi.Int32 Function(ffi.Int32 pid, ffi.Pointer status, ffi.Int32 options); +typedef _waitpid_dart = int Function(int pid, ffi.Pointer status, int options); + +typedef _chdir_c = ffi.Int32 Function(ffi.Pointer path); +typedef _chdir_dart = int Function(ffi.Pointer path); + base class Winsize extends ffi.Struct { @ffi.Uint16() external int ws_row; @@ -90,8 +96,9 @@ class PtySession { final dup2 = libc.lookupFunction<_dup2_c, _dup2_dart>('dup2'); final execvp = libc.lookupFunction<_execvp_c, _execvp_dart>('execvp'); final ioctl = libc.lookupFunction<_ioctl_c, _ioctl_dart>('ioctl'); + final chdir = libc.lookupFunction<_chdir_c, _chdir_dart>('chdir'); - // 1. Open master PTY (O_RDWR = 2, O_NOCTTY = 0x00000400) + // 1. Prepare master PTY final masterFd = posixOpenpt(2 | 0x00000400); if (masterFd < 0) { throw OSError('Failed to open pseudo-terminal master'); @@ -119,25 +126,46 @@ class PtySession { env.remove('TMUX'); env.remove('TMUX_PANE'); - // 3. Fork child process + // 3. Pre-allocate ALL structures on the heap before fork() for async-signal-safety (ยง6.7) + final pathPtr = slaveName.toNativeUtf8(); + final exePtr = executable.toNativeUtf8(); + final workDirPtr = workingDirectory?.toNativeUtf8(); + + final argsCount = arguments.length; + final argv = malloc>(argsCount + 2); + argv[0] = exePtr.cast(); + + final allocatedArgs = >[]; + for (var i = 0; i < argsCount; i++) { + final ptr = arguments[i].toNativeUtf8(); + allocatedArgs.add(ptr); + argv[i + 1] = ptr.cast(); + } + argv[argsCount + 1] = ffi.Pointer.fromAddress(0); + + // 4. Fork child process final pid = fork(); if (pid < 0) { close(masterFd); + malloc.free(pathPtr); + malloc.free(exePtr); + if (workDirPtr != null) malloc.free(workDirPtr); + malloc.free(argv); + for (final p in allocatedArgs) { + malloc.free(p); + } throw OSError('Failed to fork child process'); } if (pid == 0) { - // --- CHILD PROCESS BRANCH --- + // --- CHILD PROCESS BRANCH (Strictly async-signal-safe syscalls only!) --- setsid(); - final pathPtr = slaveName.toNativeUtf8(); final slaveFd = open(pathPtr.cast(), 2); - malloc.free(pathPtr); if (slaveFd < 0) { exit(-1); } - // TIOCSCTTY = 0x540E ioctl(slaveFd, 0x540E, ffi.Pointer.fromAddress(0)); dup2(slaveFd, 0); @@ -149,25 +177,23 @@ class PtySession { close(slaveFd); } - if (workingDirectory != null) { - Directory.current = workingDirectory; + if (workDirPtr != null) { + chdir(workDirPtr.cast()); } - final exePtr = executable.toNativeUtf8(); - final argsCount = arguments.length; - final argv = malloc>(argsCount + 2); - argv[0] = exePtr.cast(); - - for (var i = 0; i < argsCount; i++) { - argv[i + 1] = arguments[i].toNativeUtf8().cast(); - } - argv[argsCount + 1] = ffi.Pointer.fromAddress(0); - execvp(exePtr.cast(), argv); exit(-2); } // --- PARENT PROCESS BRANCH --- + malloc.free(pathPtr); + malloc.free(exePtr); + if (workDirPtr != null) malloc.free(workDirPtr); + malloc.free(argv); + for (final p in allocatedArgs) { + malloc.free(p); + } + return PtySession._( masterFd: masterFd, slaveName: slaveName, @@ -246,6 +272,12 @@ class PtySession { ffi.Int32 Function(ffi.Int32 pid, ffi.Int32 sig), int Function(int pid, int sig) >('kill'); - kill(childPid, 15); + kill(childPid, 15); // SIGTERM = 15 + + // Reap child zombie process (non-blocking WNOHANG = 1) + final waitpid = libc.lookupFunction<_waitpid_c, _waitpid_dart>('waitpid'); + final statusPtr = calloc(); + waitpid(childPid, statusPtr, 1); + calloc.free(statusPtr); } } diff --git a/.agents/skills/multi-agent-mux-ui/packages/mam_pty/test/pty_runtime_test.dart b/.agents/skills/multi-agent-mux-ui/packages/mam_pty/test/pty_runtime_test.dart index 5ca63a1..e0460b5 100644 --- a/.agents/skills/multi-agent-mux-ui/packages/mam_pty/test/pty_runtime_test.dart +++ b/.agents/skills/multi-agent-mux-ui/packages/mam_pty/test/pty_runtime_test.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:io'; import 'package:mam_pty/mam_pty.dart'; import 'package:test/test.dart';