Subject: bug#79201: 30.1.90; set-process-thread can permanently break fd_callback_info slots

From: Eli Zaretskii <[email-masked]>
Date: Thu, 14 Aug 2025 07:39:34 +0300

> From: Spencer Baugh <[email-masked]>
> Cc: [email-masked],  [email-masked],  [email-masked],
>    [email-masked]
> Date: Wed, 13 Aug 2025 14:36:29 -0400
> 
> Eli Zaretskii <[email-masked]> writes:
> 
> >> From: Spencer Baugh <[email-masked]>
> >> Cc: [email-masked],  [email-masked],  [email-masked],
> >>    [email-masked]
> >> Date: Wed, 13 Aug 2025 12:46:39 -0400
> >> 
> >> > Could the above scenario be the reason for what you see?
> >> 
> >> No, because the non-nil waiting_thread is seen in make-process, for a
> >> process and file descriptor that is newly created.
> >
> > Then I think the descriptors was closed without clearing the
> > .waiting_thread member.  So that goes back to what I suggested
> > up-thread: delete_read_fd and delete_write_fd should clear these
> > members.  They are called either after closing the descriptor or when
> > we stop reading/writing to them, so their .waiting_thread member is no
> > longer useful.
> 
> That doesn't explain why this is happening, though.  Descriptors are
> always closed without clearing the .waiting_thread member.  Clearing
> .waiting_thread is clear_waiting_thread_info's job.  Why isn't it
> happening?

clear_waiting_thread_info is called when some thread returns from
wait_reading_process_output.  If a thread didn't return, but is
instead stuck in the call to pselect, another thread can run and
access the descriptors.

I think if you want to understand exactly how this happens, you need
to trace the places that close the descriptors.  AFAIU, the scenario
where make-process reuses a descriptor already marked with
.waiting_thread of another thread is because that descriptor was
recently closed.  Otherwise, it's not possible for make-process to get
a descriptor which is already in use.