Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 31, 2018 Terminating multiple processes | ||||
---|---|---|---|---|
| ||||
Attachments:
| So, I have an application which has a sort of nano-services architecture, basically it is a set of communicating processes. Terminating those processes blocked on an input channel is quite easy, send a terminate message on the input channel. But what about a process that has no input channel, one that is blocked on OS events?
Is there a way of forcibly, but nicely, terminating a spawned process that never executes `receive()`?
--
Russel.
===========================================
Dr Russel Winder t: +44 20 7585 2200
41 Buckmaster Road m: +44 7770 465 077
London SW11 1EN, UK w: www.russel.org.uk
|
January 31, 2018 Re: Terminating multiple processes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russel Winder | On 1/31/18 12:44 PM, Russel Winder wrote:
> So, I have an application which has a sort of nano-services
> architecture, basically it is a set of communicating processes.
> Terminating those processes blocked on an input channel is quite easy,
> send a terminate message on the input channel. But what about a process
> that has no input channel, one that is blocked on OS events?
>
> Is there a way of forcibly, but nicely, terminating a spawned process
> that never executes `receive()`?
>
You talking about processes or threads? `receive` I believe is an inter-thread channel, no?
Terminating processes is generally done via signals or in the case of windows, calling the right system call.
Threads are another story. Typically, you need to have the thread check periodically for a termination event. There's no "nice" way to do it out of band.
In my experience, the best way to do it is to never block, but use some sort of "wait on input" for any would-be-blocking operation. You can use a large timeout, like 1 second, if immediate termination isn't important.
If you are using Fibers, and all your i/o is done using some event-based system (e.g. vibe.d), then things can be easier.
-Steve
|
January 31, 2018 Re: Terminating multiple processes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russel Winder | On Wednesday, 31 January 2018 at 17:44:37 UTC, Russel Winder wrote:
> So, I have an application which has a sort of nano-services architecture, basically it is a set of communicating processes. Terminating those processes blocked on an input channel is quite easy, send a terminate message on the input channel. But what about a process that has no input channel, one that is blocked on OS events?
>
> Is there a way of forcibly, but nicely, terminating a spawned process that never executes `receive()`?
Assuming your're talking about threads: there's no secure method of forcing the thread to stop. Threads share the state (eg. can hold the locks) and killing them is always risky.
If your threads are blocked reading the socket, you probably can close these sockets and exit after the read error.
Another way is to use atomic flag indicating that thread needs to be interrupted.
After any blocking operation, the thread have to check this flag and finish the job.
It's good to use timeouts (eg socket timeout) in such scenario (if possible).
Arek
|
February 01, 2018 Re: Terminating multiple processes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer Attachments:
| On Wed, 2018-01-31 at 13:26 -0500, Steven Schveighoffer via Digitalmars-d-learn wrote: > […] > You talking about processes or threads? `receive` I believe is an inter-thread channel, no? These are threads with no shared memory, just message passing via channels. I think of them as processes, but not OS processes. My poor choose of names, I should just have said threads. > Terminating processes is generally done via signals or in the case > of > windows, calling the right system call. Indeed. usually SIGHUP or SIGTERM, but never SIGKILL. > Threads are another story. Typically, you need to have the thread > check > periodically for a termination event. There's no "nice" way to do it > out > of band. This is what I was fearing. Of course from a theoretical standpoint it is the right way to do things. > In my experience, the best way to do it is to never block, but use > some > sort of "wait on input" for any would-be-blocking operation. You can > use > a large timeout, like 1 second, if immediate termination isn't > important. The thread in question is usually blocked in an inotify wait state having no input channel. It seems I will have to manufacture a select. I think this is what is missing in D, or at least my knowledge of it. In Go, I can set up a select between channels and block, no need for a timeout, an input on either channel causes a wakeup. The code then has to work out which channel caused the wakeup. On the other hand DInotify doesn't provide a channel style blocking wait, so select isn't an option. > If you are using Fibers, and all your i/o is done using some event- > based > system (e.g. vibe.d), then things can be easier. I am not sure I want to get into single-threaded event queues, but maybe I should. I like the dataflow approach, it is simpler for me to reason about. -- Russel. =========================================== Dr Russel Winder t: +44 20 7585 2200 41 Buckmaster Road m: +44 7770 465 077 London SW11 1EN, UK w: www.russel.org.uk |
February 01, 2018 Re: Terminating multiple processes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arek Attachments:
| On Wed, 2018-01-31 at 22:15 +0000, Arek via Digitalmars-d-learn wrote: > […] > Assuming your're talking about threads: there's no secure method of forcing the thread to stop. Threads share the state (eg. can hold the locks) and killing them is always risky. I am indeed talking threads not OS processes. I just like working with (processes|tasks) submitted to a thread pool, but this can lead to jargon use problems. > If your threads are blocked reading the socket, you probably can close these sockets and exit after the read error. The problem is actually a thread blocked in an inotify blocking read. As both Steven and yourself have pointed out I am going to have to use a timeout to check the state of the application. > Another way is to use atomic flag indicating that thread needs to > be interrupted. > After any blocking operation, the thread have to check this flag > and finish the job. > It's good to use timeouts (eg socket timeout) in such scenario > (if possible). I guess there is a choice here between shared memory to set the termination flag, or using an input channel and sending the termination message. I think the latter may be preferable, and certainly more consistent with how the other threads terminate. Thanks to you and Steven for confirming what I had been fearing, but wondered if there was an easier (albeit less theoretically sound) one. -- Russel. =========================================== Dr Russel Winder t: +44 20 7585 2200 41 Buckmaster Road m: +44 7770 465 077 London SW11 1EN, UK w: www.russel.org.uk |
February 01, 2018 Re: Terminating multiple processes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russel Winder | On Thursday, 1 February 2018 at 11:42:32 UTC, Russel Winder wrote: > On Wed, 2018-01-31 at 22:15 +0000, Arek via Digitalmars-d-learn wrote: >> > […] > > The problem is actually a thread blocked in an inotify blocking read. As both Steven and yourself have pointed out I am going to have to use a timeout to check the state of the application. > Try to use inotify in non-blocking mode (an example here: https://gist.github.com/pkrnjevic/6016356) with select or epoll and timeouts. > > I guess there is a choice here between shared memory to set the termination flag, or using an input channel and sending the termination message. I think the latter may be preferable, and certainly more consistent with how the other threads terminate. > I would use shared memory here (eg. atomic bool) because any communication channel introduces possibility of further blocking problems. Arek |
February 01, 2018 Re: Terminating multiple processes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arek Attachments:
| On Thu, 2018-02-01 at 12:15 +0000, Arek via Digitalmars-d-learn wrote: > […] > Try to use inotify in non-blocking mode (an example here: https://gist.github.com/pkrnjevic/6016356) with select or epoll and timeouts. Isn't there a C++ binding for the C API? I am using DInotify which is a D binding. I will be checking soon but I am assuming there is a timeout version so I can loop to check the application state. > > > > I guess there is a choice here between shared memory to set the termination flag, or using an input channel and sending the termination message. I think the latter may be preferable, and certainly more consistent with how the other threads terminate. > > > > I would use shared memory here (eg. atomic bool) because any communication channel introduces possibility of further blocking problems. A priori I am not convinced. I have used a state variable in C++ and Python code where there is no channel system, but in Go, Groovy/GPars, using channels is always preferable. Given the channel has a "read if there is something to read" there can't be a blocking problem – if the channel system is a good one. -- Russel. =========================================== Dr Russel Winder t: +44 20 7585 2200 41 Buckmaster Road m: +44 7770 465 077 London SW11 1EN, UK w: www.russel.org.uk |
February 01, 2018 Re: Terminating multiple processes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russel Winder | On Thursday, 1 February 2018 at 12:30:24 UTC, Russel Winder wrote: > On Thu, 2018-02-01 at 12:15 +0000, Arek via Digitalmars-d-learn wrote: >> > […] >> Try to use inotify in non-blocking mode (an example here: https://gist.github.com/pkrnjevic/6016356) with select or epoll and timeouts. > > Isn't there a C++ binding for the C API? > > I am using DInotify which is a D binding. I will be checking soon but I am assuming there is a timeout version so I can loop to check the application state. > DInitify doesn't cover full capabilities of the inotify API. Especially it doesn't utilize newer inotify_init1 syscall and doesn't expose 'select' interface. This C++ wrapper may be interesting for you: https://github.com/erikzenker/inotify-cpp But I haven't used it. >> >> I would use shared memory here (eg. atomic bool) because any communication channel introduces possibility of further blocking problems. > > A priori I am not convinced. I have used a state variable in C++ and Python code where there is no channel system, but in Go, Groovy/GPars, using channels is always preferable. Given the channel has a "read if there is something to read" there can't be a blocking problem – if the channel system is a good one. You may be right. But interrupting the thread is very low level mechanism. Eg in Java, it is incorporated into Thread class: thread has method 'interrupt()' which sets the flag, and there is property 'isInterrupted()'. Usually your thread code have something like while(!Thread.currentThread().isInterrupted()) { /* do something*/ } I would use similar pattern. Arek |
February 02, 2018 Re: Terminating multiple processes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russel Winder | On Thursday, 1 February 2018 at 11:42:32 UTC, Russel Winder wrote:
> The problem is actually a thread blocked in an inotify blocking read. As both Steven and yourself have pointed out I am going to have to use a timeout to check the state of the application.
There are better solutions (select/...), But couldn't you in theory just send a custom signal to the thread (which you ignore), and then check for the exit flag after the syscall returned EINTR?
The DInotify wrapper might of course have the retry loop hardcoded; I didn't check.
—David
|
February 02, 2018 Re: Terminating multiple processes | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger Attachments:
| On Fri, 2018-02-02 at 01:09 +0000, David Nadlinger via Digitalmars-d- learn wrote: > On Thursday, 1 February 2018 at 11:42:32 UTC, Russel Winder wrote: > > The problem is actually a thread blocked in an inotify blocking read. As both Steven and yourself have pointed out I am going to have to use a timeout to check the state of the application. > > There are better solutions (select/...), But couldn't you in theory just send a custom signal to the thread (which you ignore), and then check for the exit flag after the syscall returned EINTR? I think I am going to go the (select|poll|epoll) on the file descriptor with a timeout and then the read if that is appropriate or check the input channel for the terminate token if that is appropriate. The question whether to do this in my code or create a "read with timeout" in dinotify > The DInotify wrapper might of course have the retry loop hardcoded; I didn't check. Dinotify adds the tree monitoring as an extra over the inotify API but U do not see any timeout related things. -- Russel. =========================================== Dr Russel Winder t: +44 20 7585 2200 41 Buckmaster Road m: +44 7770 465 077 London SW11 1EN, UK w: www.russel.org.uk |
Copyright © 1999-2021 by the D Language Foundation