@@ -150,23 +150,83 @@ public void GetProcessTmpDir_ChildProcess_ReadsTmpdir()
150150 string customTmpDir = "/custom/tmp/test" ;
151151 ProcessStartInfo psi = new ( "sleep" , "30" )
152152 {
153- Environment = { [ "TMPDIR" ] = customTmpDir } ,
154153 UseShellExecute = false ,
155154 } ;
155+ psi . Environment [ "TMPDIR" ] = customTmpDir ;
156156
157157 using Process child = Process . Start ( psi ) ;
158158 try
159159 {
160- string result = PidIpcEndpoint . GetProcessTmpDir ( child . Id , out bool environReadable ) ;
160+ // Read the child's environ directly for diagnostics
161+ string environPath = $ "/proc/{ child . Id } /environ";
162+ string environPerms = "unknown" ;
163+ try
164+ {
165+ environPerms = File . GetUnixFileMode ( environPath ) . ToString ( ) ;
166+ }
167+ catch ( Exception ex )
168+ {
169+ environPerms = $ "error: { ex . GetType ( ) . Name } : { ex . Message } ";
170+ }
171+
172+ byte [ ] rawEnviron = Array . Empty < byte > ( ) ;
173+ string environContent = string . Empty ;
174+ string [ ] envVars = Array . Empty < string > ( ) ;
175+ string tmpdirEntry = null ;
176+ string environReadError = null ;
177+ try
178+ {
179+ rawEnviron = File . ReadAllBytes ( environPath ) ;
180+ environContent = Encoding . UTF8 . GetString ( rawEnviron ) ;
181+ envVars = environContent . Split ( new [ ] { '\0 ' } , StringSplitOptions . RemoveEmptyEntries ) ;
182+ tmpdirEntry = Array . Find ( envVars , v => v . StartsWith ( "TMPDIR=" , StringComparison . Ordinal ) ) ;
183+ }
184+ catch ( Exception ex )
185+ {
186+ environReadError = $ "{ ex . GetType ( ) . Name } : { ex . Message } ";
187+ }
188+
189+ string diagnostics = $ "Child PID: { child . Id } , "
190+ + $ "child exited: { child . HasExited } , "
191+ + $ "environ path: { environPath } , "
192+ + $ "environ permissions: { environPerms } , "
193+ + $ "parent TMPDIR: '{ Environment . GetEnvironmentVariable ( "TMPDIR" ) ?? "(not set)" } ', "
194+ + $ "psi.Environment TMPDIR: '{ psi . Environment [ "TMPDIR" ] } ', "
195+ + $ "current user: { Environment . UserName } , ";
196+
197+ if ( environReadError != null )
198+ {
199+ diagnostics += $ "environ read error: { environReadError } ";
200+ }
201+ else
202+ {
203+ diagnostics += $ "environ size: { rawEnviron . Length } bytes, "
204+ + $ "env var count: { envVars . Length } , "
205+ + $ "TMPDIR entry: '{ tmpdirEntry ?? "(not found)" } ', "
206+ + $ "first 200 chars of environ: '{ ( environContent . Length > 200 ? environContent . Substring ( 0 , 200 ) : environContent ) . Replace ( '\0 ' , '|' ) } '";
207+ }
208+
209+ string result ;
210+ bool environReadable ;
211+ try
212+ {
213+ result = PidIpcEndpoint . GetProcessTmpDir ( child . Id , out environReadable ) ;
214+ }
215+ catch ( Exception ex )
216+ {
217+ Assert . Fail ( $ "GetProcessTmpDir threw { ex . GetType ( ) . Name } : { ex . Message } . { diagnostics } ") ;
218+ return ;
219+ }
220+
161221 if ( environReadable )
162222 {
163- // environ was readable — expect the custom TMPDIR
164- Assert . Equal ( customTmpDir , result ) ;
223+ Assert . True ( result == customTmpDir ,
224+ $ "Expected ' { customTmpDir } ' but got ' { result } '. { diagnostics } " ) ;
165225 }
166226 else
167227 {
168- // Systems with hidepid or restricted /proc permissions fall back to default
169- Assert . Equal ( Path . GetTempPath ( ) , result ) ;
228+ Assert . True ( result == Path . GetTempPath ( ) ,
229+ $ "environ was not readable; expected fallback ' { Path . GetTempPath ( ) } ' but got ' { result } '. { diagnostics } " ) ;
170230 }
171231 }
172232 finally
0 commit comments