Subj : Re: A pity that there is no forkall() which clones threads To : comp.programming.threads From : David Hopwood Date : Tue Mar 08 2005 03:45 am Marcin 'Qrczak' Kowalczyk wrote: > David Hopwood writes: > >> On a ForkProcess call in thread T, >> >> 1. set a global flag that causes all threads except T to suspend >> if and when they reach an interruptible point. > > Doing this with a global flag would be too intrusive, it would require > amending the mechanism of delivering signals with additional checking > just for the purpose of forking. > > I send all threads Kogut signals instead (and hook to send it to newly > created threads too, and set up an exit monitor which checks for > threads that will not handle the signal because they finished). > > The handler of such signal suspends the thread. When it's resumed > after the fork, it either returns or throws the exception of thread > cancellation. Yes, that will work (although the global flag avoids complications like having to send the signal to newly created threads, so I would still probably do it that way). >> 2. wait until all threads have suspended except T, and possibly some >> threads that were already running interruptible foreign code at >> the time of the ForkProcess call. > > Yes, the semantics should be like this. It's ugly that the forker has > to peek inside thread internals to determine whether it should be > counted or not. And it's ugly to add a flag to a thread state only > to determine whether it's evaporable at fork. > > And they will leak resources. For example if the call is getaddrinfo, > it will leave open sockets. I think that's unavoidable. Uninterruptible blocking primitives like getaddrinfo are just broken for use in concurrent languages. Windows has asynchronous DNS APIs; it's about time POSIX caught up. >>>Maybe I should introduce something which says "when you want to >>>interrupt me while I'm making this foreign call, send me SIGUSR1". >> >>Unix signals and threads don't mix very well; you probably want to use >>pthread_cancel instead. > > No, a Kogut signal doesn't necessarily imply cancellation. And even > in case it does, it's not immediate - it's propagated as an exception. > There is no Kogut API which could be mapped to pthread_cancel. Yes, but it's possible to implement signals in terms of cancellation. Suppose that you have a pool of pthreads that only run foreign functions, separate from the Kogut interpreter. When you need to interrupt a foreign function with a signal, cancel that pthread, and signal the corresponding Kogut thread (which is blocked waiting for the foreign function to finish). The fact that you have lost a pthread from the pool isn't a problem because they are interchangeable -- new pthreads will be created as necessary to run more foreign code. With a little care, callbacks from foreign functions into Kogut can also be handled correctly, although that's enough to give anyone a headache. > In particular in the case of forking the signal causes suspension and > later in one of the processes the computation continues, so interruption > can't be made with pthread_cancel. pthread_cancel isn't needed when forking; in that case you are only relying on evaporation-on-fork and Kogut signals. > I tried making the change of interruption by Unix signals, but it was > getting very ugly. [...] Yep. > Is there any way to interrupt waitpid, other than a Unix signal or > pthread_cancel? Random, possibly unworkable idea: maybe you can have a hidden pthread that just does a wait() on all child processes in a loop, and stores the results in a shared structure? This pthread would be started the first time WaitForProcess is used, or the first time it is used in the child after a fork. > Can I assume that pthread_getspecific is usable in a signal handler? I don't know. > It's not easy to provide an interface to pthread_kill because if Unix > signals are unblocked in other threads, then the above problems appear, > and if they are blocked then pthread_kill obviously won't work. Hmm. You could possibly use pthread_kill in a similar way to what I suggested above for pthread_cancel. Not sure if that helps you. >>I was originally thinking that it would indicate both that the thread >>agrees to be evaporated on fork, and that it can be interrupted using >>pthread_cancel with cancellation type PTHREAD_CANCEL_ASYNCHRONOUS (see >>the man page). > > POSIX cancellation doesn't map well to Kogut threads. The concept > of blocking Kogut signals is similar to POSIX cancellability (I have > similar three effective states, the difference is that the synchronous > mode is not the default), but being similar doesn't mean that one > mechanism can use the other. I was suggesting to only use pthread_cancel for pthreads that are running foreign code. Did I explain this well enough above? -- David Hopwood .