digitalmars.D.learn - Terminating multiple processes
- Russel Winder (14/14) Jan 31 2018 So, I have an application which has a sort of nano-services
- Steven Schveighoffer (14/23) Jan 31 2018 You talking about processes or threads? `receive` I believe is an
- Russel Winder (27/47) Feb 01 2018 [=E2=80=A6]
- Arek (14/22) Jan 31 2018 Assuming your're talking about threads: there's no secure method
- Russel Winder (22/34) Feb 01 2018 I am indeed talking threads not OS processes. I just like working with
- Arek (8/19) Feb 01 2018 Try to use inotify in non-blocking mode (an example here:
- Russel Winder (19/33) Feb 01 2018 Isn't there a C++ binding for the C API?
- Arek (17/38) Feb 01 2018 DInitify doesn't cover full capabilities of the inotify API.
- Russel Winder (20/37) Feb 02 2018 Hummm=E2=80=A6 sounds like I need to look to create a pull request to ge...
- David Nadlinger (8/11) Feb 01 2018 There are better solutions (select/...), But couldn't you in
- Russel Winder (16/27) Feb 02 2018 I think I am going to go the (select|poll|epoll) on the file descriptor
- Russel Winder (20/34) Feb 05 2018 [=E2=80=A6]
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()`? --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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
Jan 31 2018
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
Jan 31 2018
On Wed, 2018-01-31 at 13:26 -0500, Steven Schveighoffer via Digitalmars-d-learn wrote:=20[=E2=80=A6]You talking about processes or threads? `receive` I believe is an=20 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=20 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=20 periodically for a termination event. There's no "nice" way to do it out=20 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=20 sort of "wait on input" for any would-be-blocking operation. You can use=20 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=20 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. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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
Feb 01 2018
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
Jan 31 2018
On Wed, 2018-01-31 at 22:15 +0000, Arek via Digitalmars-d-learn wrote:=20[=E2=80=A6]Assuming your're talking about threads: there's no secure method=20 of forcing the thread to stop. Threads share the state (eg. can=20 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=20 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.=20Another way is to use atomic flag indicating that thread needs to=20 be interrupted. After any blocking operation, the thread have to check this flag=20 and finish the job. It's good to use timeouts (eg socket timeout) in such scenario=20 (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. =20 --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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
Feb 01 2018
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:Try to use inotify in non-blocking mode (an example here: https://gist.github.com/pkrnjevic/6016356) with select or epoll and timeouts.[…] 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.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
Feb 01 2018
On Thu, 2018-02-01 at 12:15 +0000, Arek via Digitalmars-d-learn wrote:=20[=E2=80=A6]Try to use inotify in non-blocking mode (an example here:=20 https://gist.github.com/pkrnjevic/6016356) with select or epoll=20 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.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 =E2=80=93 if = the channel system is a good one. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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=20 I guess there is a choice here between shared memory to set the=20 termination flag, or using an input channel and sending the=20 termination message. I think the latter may be preferable, and=20 certainly more consistent with how the other threads terminate. =20=20 I would use shared memory here (eg. atomic bool) because any=20 communication channel introduces possibility of further blocking=20 problems.
Feb 01 2018
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: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.[…]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.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. ArekI 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.
Feb 01 2018
On Thu, 2018-02-01 at 20:13 +0000, Arek via Digitalmars-d-learn wrote:=20[=E2=80=A6]DInitify doesn't cover full capabilities of the inotify API. Especially it doesn't utilize newer inotify_init1 syscall and=20 doesn't expose 'select' interface. This C++ wrapper may be interesting for you:=20 https://github.com/erikzenker/inotify-cpp But I haven't used it.Hummm=E2=80=A6 sounds like I need to look to create a pull request to get t= o dinotify 0.2.3 or even 0.3.0.[=E2=80=A6]=20You may be right. But interrupting the thread is very low level=20 mechanism. Eg in Java, it is incorporated into Thread class: thread has=20 method 'interrupt()' which sets the flag, and there is property 'isInterrupted()'. Usually=20 your thread code have something like =20 while(!Thread.currentThread().isInterrupted()) { /* do=20 something*/ } I would use similar pattern.I do want to avoid such low-level things, they may be required for building libraries, but they seem totally the wrong level of concept for an application. I am definitely headed to the (select|poll|epoll) on the inotify file descriptor to get the timeout, and then either read or check the input channel for termination or an atomic Boolean state variable. Channels seem most likely since parent threads send a terminating token. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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
Feb 02 2018
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
Feb 01 2018
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: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 dinotifyThe problem is actually a thread blocked in an inotify blocking=20 read. As both Steven and yourself have pointed out I am going=20 to have to use a timeout to check the state of the application.=20 There are better solutions (select/...), But couldn't you in=20 theory just send a custom signal to the thread (which you=20 ignore), and then check for the exit flag after the syscall=20 returned EINTR?The DInotify wrapper might of course have the retry loop=20 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. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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
Feb 02 2018
On Fri, 2018-02-02 at 20:14 +0000, David Nadlinger wrote:=20[=E2=80=A6]That sounds entirely sensible. Your original question was whether it was=20 possible to terminate threads blocked in a syscall, though. Signals=20 allow you to do that on POSIX for many "slow" syscalls, by making it=20 return EINTR. You would check whatever channel/atomic flag/=E2=80=A6 mechanism=20 you use to signal termination before continuing to block by reissuing=20 the syscall. =20 I haven't tested how `read` behaves for inotify myself, but inotify(7)=20 suggests that it indeed handles signals this way.[=E2=80=A6] After some discussions, Dmitry acted very quickly and added a timeout read to the blocking read in dinotify. This solves my problem "at a stroke" as I can now block waiting for a specific time on inotify and then check the input channel for a time and repeat. Not really busy wait just a sequence of blocking reads with timeouts. The important thing is that With very little latency, the thread is checking two things. DInotify 0.3.0 will likely appear soon in Dub. It would be good to get it packaged for Debian. I will take up an invitation to submit a ready made package for the Debian D packaging team. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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
Feb 05 2018