www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - ctrl+c and destructors

reply "Adam D. Ruppe" <destructionator gmail.com> writes:
Is there anything we can do to automatically clean up if the user 
hits ctrl+c on Linux?

I just had my system get messed up because I was allocating 
shared memory with the X server, which was released in the 
destructor... but that never got called because I killed the 
program with ctrl+c. Then the system ran out of shm handles and I 
had to clean that up before i could start a bunch of programs 
again.

Of course, a possible solution is to set up a signal handler in 
my own program, but even with that, tracking all the dtors that 
need to actually be called sounds difficult, especially as the 
program gets more involved.


Is it possible to either:

1) make ctrl+c throw an exception so destructor cleanup happens 
normally

or

2) call all the destructors and kill the program from inside a 
signal handler without throwing a normal exception; it doesn't 
matter to me that it is unrecoverable, I just need these handles 
cleaned up.


My backup plan is to just ignore the ctrl+c signal, or maybe set 
a flag in my event loop and terminate the program that way.
Sep 29 2013
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Sep 30, 2013 at 03:48:07AM +0200, Adam D. Ruppe wrote:
 Is there anything we can do to automatically clean up if the user
 hits ctrl+c on Linux?
 
 I just had my system get messed up because I was allocating shared
 memory with the X server, which was released in the destructor...
 but that never got called because I killed the program with ctrl+c.
 Then the system ran out of shm handles and I had to clean that up
 before i could start a bunch of programs again.
 
 Of course, a possible solution is to set up a signal handler in my
 own program, but even with that, tracking all the dtors that need to
 actually be called sounds difficult, especially as the program gets
 more involved.

Well, ctrl-C can be handled, so the way I'd do it is to set up a signal handler for SIGINT and have it write something to a self-pipe read by the event handler, then the event handler can throw an Exception (which should cause dtors to run as the stack unwinds). I've no idea how signals work in Windows so I don't know if it's even possible to have a consistent D implementation of signal-handling. T -- Change is inevitable, except from a vending machine.
Sep 29 2013
prev sibling next sibling parent "PauloPinto" <pjmlp progtools.org> writes:
On Monday, 30 September 2013 at 02:13:47 UTC, H. S. Teoh wrote:
 On Mon, Sep 30, 2013 at 03:48:07AM +0200, Adam D. Ruppe wrote:
 Is there anything we can do to automatically clean up if the 
 user
 hits ctrl+c on Linux?
 
 I just had my system get messed up because I was allocating 
 shared
 memory with the X server, which was released in the 
 destructor...
 but that never got called because I killed the program with 
 ctrl+c.
 Then the system ran out of shm handles and I had to clean that 
 up
 before i could start a bunch of programs again.
 
 Of course, a possible solution is to set up a signal handler 
 in my
 own program, but even with that, tracking all the dtors that 
 need to
 actually be called sounds difficult, especially as the program 
 gets
 more involved.

Well, ctrl-C can be handled, so the way I'd do it is to set up a signal handler for SIGINT and have it write something to a self-pipe read by the event handler, then the event handler can throw an Exception (which should cause dtors to run as the stack unwinds). I've no idea how signals work in Windows so I don't know if it's even possible to have a consistent D implementation of signal-handling. T

Windows uses kernel level exceptions for some signals, known as Structured Exception Handling. For others, callback handlers are used instead, similar to signal handlers. http://msdn.microsoft.com/library/windows/desktop/ms680657.aspx signal() is available, http://msdn.microsoft.com/en-us/library/xdkz3x12%28v=vs.110%29.aspx However, since I never used signal on Windows, here is the specific Windows API for the same purpose, http://msdn.microsoft.com/en-us/library/ms686016%28VS.85%29.aspx -- Paulo
Sep 29 2013
prev sibling next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Monday, 30 September 2013 at 01:48:09 UTC, Adam D. Ruppe wrote:
 Is there anything we can do to automatically clean up if the 
 user hits ctrl+c on Linux?

 I just had my system get messed up because I was allocating 
 shared memory with the X server, which was released in the 
 destructor... but that never got called because I killed the 
 program with ctrl+c. Then the system ran out of shm handles and 
 I had to clean that up before i could start a bunch of programs 
 again.

 Of course, a possible solution is to set up a signal handler in 
 my own program, but even with that, tracking all the dtors that 
 need to actually be called sounds difficult, especially as the 
 program gets more involved.


 Is it possible to either:

 1) make ctrl+c throw an exception so destructor cleanup happens 
 normally

 or

 2) call all the destructors and kill the program from inside a 
 signal handler without throwing a normal exception; it doesn't 
 matter to me that it is unrecoverable, I just need these 
 handles cleaned up.


 My backup plan is to just ignore the ctrl+c signal, or maybe 
 set a flag in my event loop and terminate the program that way.

especially the last post: http://forum.dlang.org/thread/crviwhvbfruxfnwawirs forum.dlang.org
Sep 30 2013
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-10-01 06:54, PauloPinto wrote:

 I would say the main reason is that anyone can replace the current set
 of signals, thus breaking what might be druntime's signal handling.

If druntime has a default signal handler and the user replaces that. It's up to the user to call the original signal handler so everything is properly destructed/finalized. It's the same problem with the GC and all the other handlers that druntime has that the user can override. I would consider these very advanced features and not something a user should be fiddling with every day. -- /Jacob Carlborg
Oct 01 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-10-01 13:19, PauloPinto wrote:

 I just remember that you also have the added problem that signal
 handlers are very limited in what you are allowed to do, with the set of
 restrictions and guarantees not being portable across all POSIX systems.

 Specially the tricks of notifying the application a signal has happened,
 after signal returns and the whole story of redoing interrupted system
 calls.

druntime already handles SIGSEGV signals, at least for Linux: https://github.com/D-Programming-Language/druntime/blob/master/src/etc/linux/memoryerror.d -- /Jacob Carlborg
Oct 01 2013
parent Martin Nowak <code dawg.eu> writes:
On 10/01/2013 10:06 PM, Maxim Fomin wrote:
 Is this feature working as built-in or by demand?

This can't be built-in because signal handlers are global and you cannot anticipate in which environments druntime get used.
Oct 01 2013
prev sibling parent reply Paulo Pinto <pjmlp progtools.org> writes:
Am 01.10.2013 22:16, schrieb Maxim Fomin:
 On Tuesday, 1 October 2013 at 19:55:17 UTC, monarch_dodra wrote:
 On Tuesday, 1 October 2013 at 03:58:04 UTC, Nick Sabalausky wrote:
 You know, this sounds like something that really should fall squarely in
 the category of "do the right thing by default". Is there any reason
 druntime can't be made to handle this better by default?

Well, arguably, a segfault is a catastrophic error, even more serious than an assert.

In linux assert(0) causes a segfault. And the fact that detected by OS memory error is sigfault at linux and exception on windows really hurts portability.
 I'm not sure what "the right thing" would even be, apart from dying
 right there and then...?

 Even just throwing an error could be problematic (AFAIK).

Druntime can catch SIGINT and throw the exception. This means that D runtime can be easily broken by silly C code which uses its own signal handlers. I didn't tested, but believe this is already the case with respect to SIGUSR1 and SIGUSR2 which are used by druntime, so any simple code hijacking the signals can break runtime. Linux signals handlers as error mechanism is a complete disaster.

s/Linux/UNIX/g
Oct 01 2013
parent Paulo Pinto <pjmlp progtools.org> writes:
On 02.10.2013 01:59, deadalnix wrote:
 On Tuesday, 1 October 2013 at 23:32:38 UTC, Paulo Pinto wrote:
 s/Linux/UNIX/g

The described technique use some OS specific features. It can be adapted to OSX as far as I know, but POSIX do not guarantee to have all required features to implement this.

That is why I was rephrasing Maxim's statement to mean "UNIX signals handlers as error mechanism is a complete disaster." I don't do UNIX system programming at C level since 2002, but my POSIX memories, is that it is as portable as C, with its share of undefined behaviors and OS specific extensions. And if I recall correctly the behavior of what was allowed to do in the signal handler, and how UNIX/libc functions would behave upon interruption was not that stable across multiple UNIX variants. -- Paulo
Oct 02 2013
prev sibling next sibling parent "simendsjo" <simendsjo gmail.com> writes:
On Monday, 30 September 2013 at 01:48:09 UTC, Adam D. Ruppe wrote:
 Is there anything we can do to automatically clean up if the 
 user hits ctrl+c on Linux?

I believe vibe.d does this.
Sep 30 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Monday, 30 September 2013 at 02:13:47 UTC, H. S. Teoh wrote:
 Well, ctrl-C can be handled, so the way I'd do it is to set up 
 a signal
 handler for SIGINT and have it write something to a self-pipe 
 read by
 the event handler, then the event handler can throw an 
 Exception (which
 should cause dtors to run as the stack unwinds).

No you can't. But you somehow can, if you want to use some black magic : http://www.deadalnix.me/2012/03/24/get-an-exception-from-a-segfault-on-linux-x86-and-x86_64-using-some-black-magic/
Sep 30 2013
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Sep 30, 2013 at 08:44:36PM +0200, deadalnix wrote:
 On Monday, 30 September 2013 at 02:13:47 UTC, H. S. Teoh wrote:
Well, ctrl-C can be handled, so the way I'd do it is to set up a
signal handler for SIGINT and have it write something to a self-pipe
read by the event handler, then the event handler can throw an
Exception (which should cause dtors to run as the stack unwinds).

No you can't. But you somehow can, if you want to use some black magic : http://www.deadalnix.me/2012/03/24/get-an-exception-from-a-segfault-on-linux-x86-and-x86_64-using-some-black-magic/

We were talking about SIGINT, not SIGSEGV. T -- Unix is my IDE. -- Justin Whear
Sep 30 2013
prev sibling next sibling parent Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> writes:
On Mon, 30 Sep 2013 09:49:12 +0200
"Namespace" <rswhite4 googlemail.com> wrote:

 On Monday, 30 September 2013 at 01:48:09 UTC, Adam D. Ruppe wrote:
 Is there anything we can do to automatically clean up if the 
 user hits ctrl+c on Linux?

especially the last post: http://forum.dlang.org/thread/crviwhvbfruxfnwawirs forum.dlang.org

You know, this sounds like something that really should fall squarely in the category of "do the right thing by default". Is there any reason druntime can't be made to handle this better by default?
Sep 30 2013
prev sibling next sibling parent "PauloPinto" <pjmlp progtools.org> writes:
On Tuesday, 1 October 2013 at 03:58:04 UTC, Nick Sabalausky wrote:
 On Mon, 30 Sep 2013 09:49:12 +0200
 "Namespace" <rswhite4 googlemail.com> wrote:

 On Monday, 30 September 2013 at 01:48:09 UTC, Adam D. Ruppe 
 wrote:
 Is there anything we can do to automatically clean up if the 
 user hits ctrl+c on Linux?

you, especially the last post: http://forum.dlang.org/thread/crviwhvbfruxfnwawirs forum.dlang.org

You know, this sounds like something that really should fall squarely in the category of "do the right thing by default". Is there any reason druntime can't be made to handle this better by default?

I would say the main reason is that anyone can replace the current set of signals, thus breaking what might be druntime's signal handling. -- Paulo
Sep 30 2013
prev sibling next sibling parent "PauloPinto" <pjmlp progtools.org> writes:
On Tuesday, 1 October 2013 at 08:01:21 UTC, Jacob Carlborg wrote:
 On 2013-10-01 06:54, PauloPinto wrote:

 I would say the main reason is that anyone can replace the 
 current set
 of signals, thus breaking what might be druntime's signal 
 handling.

If druntime has a default signal handler and the user replaces that. It's up to the user to call the original signal handler so everything is properly destructed/finalized. It's the same problem with the GC and all the other handlers that druntime has that the user can override. I would consider these very advanced features and not something a user should be fiddling with every day.

I just remember that you also have the added problem that signal handlers are very limited in what you are allowed to do, with the set of restrictions and guarantees not being portable across all POSIX systems. Specially the tricks of notifying the application a signal has happened, after signal returns and the whole story of redoing interrupted system calls. -- Paulo
Oct 01 2013
prev sibling next sibling parent "w0rp" <devw0rp gmail.com> writes:
This is a really good question, I think! Python has a 
KeyboardInterrupt exception for this purpose. Should we perhap 
try something similar? Perhaps as a library solution? I think a 
function like some_module.registerInterruptExceptions() would be 
cool to have. If someone knows a way to do that, that would be 
cool. I'm looking at deadalnix...
Oct 01 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Monday, 30 September 2013 at 22:55:22 UTC, H. S. Teoh wrote:
 On Mon, Sep 30, 2013 at 08:44:36PM +0200, deadalnix wrote:
 On Monday, 30 September 2013 at 02:13:47 UTC, H. S. Teoh wrote:
Well, ctrl-C can be handled, so the way I'd do it is to set 
up a
signal handler for SIGINT and have it write something to a 
self-pipe
read by the event handler, then the event handler can throw an
Exception (which should cause dtors to run as the stack 
unwinds).

No you can't. But you somehow can, if you want to use some black magic : http://www.deadalnix.me/2012/03/24/get-an-exception-from-a-segfault-on-linux-x86-and-x86_64-using-some-black-magic/

We were talking about SIGINT, not SIGSEGV.

That isn't relevant here.
Oct 01 2013
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Oct 01, 2013 at 02:06:12PM +0200, deadalnix wrote:
 On Monday, 30 September 2013 at 22:55:22 UTC, H. S. Teoh wrote:
On Mon, Sep 30, 2013 at 08:44:36PM +0200, deadalnix wrote:
On Monday, 30 September 2013 at 02:13:47 UTC, H. S. Teoh wrote:
Well, ctrl-C can be handled, so the way I'd do it is to set up a
signal handler for SIGINT and have it write something to a
self-pipe read by the event handler, then the event handler can
throw an Exception (which should cause dtors to run as the stack
unwinds).

No you can't. But you somehow can, if you want to use some black magic : http://www.deadalnix.me/2012/03/24/get-an-exception-from-a-segfault-on-linux-x86-and-x86_64-using-some-black-magic/

We were talking about SIGINT, not SIGSEGV.

That isn't relevant here.

Huh? The OP was talking about cleaning up after ctrl-C, not after a segfault. I already know you can't throw exceptions from a segfault (except with heavy trickery, and yes I remember the post you linked and I know how it works). SIGINT is different because it can be handled, and the signal handler can just write a byte to a pipe read by the main event loop, outside of signal handler context. T -- Klein bottle for rent ... inquire within. -- Stephen Mulraney
Oct 01 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 1 October 2013 at 14:53:24 UTC, H. S. Teoh wrote:
 On Tue, Oct 01, 2013 at 02:06:12PM +0200, deadalnix wrote:
 On Monday, 30 September 2013 at 22:55:22 UTC, H. S. Teoh wrote:
On Mon, Sep 30, 2013 at 08:44:36PM +0200, deadalnix wrote:
On Monday, 30 September 2013 at 02:13:47 UTC, H. S. Teoh 
wrote:
Well, ctrl-C can be handled, so the way I'd do it is to set 
up a
signal handler for SIGINT and have it write something to a
self-pipe read by the event handler, then the event handler 
can
throw an Exception (which should cause dtors to run as the 
stack
unwinds).

No you can't. But you somehow can, if you want to use some black magic : http://www.deadalnix.me/2012/03/24/get-an-exception-from-a-segfault-on-linux-x86-and-x86_64-using-some-black-magic/

We were talking about SIGINT, not SIGSEGV.

That isn't relevant here.

Huh? The OP was talking about cleaning up after ctrl-C, not after a segfault. I already know you can't throw exceptions from a segfault (except with heavy trickery, and yes I remember the post you linked and I know how it works). SIGINT is different because it can be handled, and the signal handler can just write a byte to a pipe read by the main event loop, outside of signal handler context.

The signal handler cannot throw exception. If you want to do so, you need the same scafolding. ctrl+c send a signal to the program. The exact same system need to be used to throw. Obviously, you can flag something on ctrl+c so you quit you main loop, which is simpler, but not what I was answering to.
Oct 01 2013
prev sibling next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 1 October 2013 at 03:58:04 UTC, Nick Sabalausky wrote:
 You know, this sounds like something that really should fall 
 squarely in
 the category of "do the right thing by default". Is there any 
 reason
 druntime can't be made to handle this better by default?

Well, arguably, a segfault is a catastrophic error, even more serious than an assert. I'm not sure what "the right thing" would even be, apart from dying right there and then...? Even just throwing an error could be problematic (AFAIK).
Oct 01 2013
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/1/2013 3:37 PM, Jonathan M Davis wrote:
 On Tuesday, October 01, 2013 23:17:01 deadalnix wrote:
 It shouldn't in a language that have nullable type as default.

I don't see why that's relevant. If you hit a segfault - regardless of whether it's because of a memory corruption or a null pointer or whatever - it's an error that should terminate your program. If we checked for null pointers and threw NullPointerError instead of segfaulting, it would be no different except that it would be an Error being thrown. Both it and segfaults are supposed to kill your program without doing cleanup.

Right. A null pointer dereference is a logic bug in your program, and hence the program needs to stop immediately, not execute "cleanup" code. If there's one notion I'd like to terminate with prejudice, it's the notion that a running program can "recover" from bugs in itself.
Oct 01 2013
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/2/2013 10:10 AM, Sean Kelly wrote:
 If there's one notion I'd like to terminate with prejudice, it's the notion
 that a running program can "recover" from bugs in itself.

I worked on a system whose design was specifically built around trapping and recovering from segfaults (great design, and sadly, patented). Things like this are one of the primary reasons to use a systems programming language. So while I agree in the general sense, I don't think it's appropriate for the language to make a hard and fast assertion here. I think we should choose a reasonable, safe default, but make it overridable. That's pretty much the design philosophy of Druntime.

D being a systems programming language, you can pursue whatever design you like with it, including bad designs :-) Although I haven't seen the system you describe, I'm very skeptical that it found the solution to the problem of a program successfully continuing after it has crashed due to program bugs. I remain firmly convinced that that is an utterly wrong and doomed approach to the problem of reliability.
Oct 02 2013
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/2/2013 6:15 PM, Adam D. Ruppe wrote:
 Segfaults aren't necessarily bugs... though I'm not sure if a userspace handler
 can do much about it. But from a kernel perspective, they can be generated by
 page faults too, which can be successfully handled by loading the requested
 memory block (e.g. from a swap file) and then retrying the operation, or
copying
 the page into a writable location and mapping that in; hardware assisted
 copy-on-write.

That's true, and in fact I implemented a generational GC once that relied on catching seg faults from invalid writes to keep track of which pages were 'dirty'. It did work fine, although it turned out to be too slow.
 I've never tried to do this in a unix program so I don't know how much you can
 do, but presumably Sean's example did something along these lines, so it would
 be by design rather than bugs.

If that is the design, then I misunderstood it.
Oct 02 2013
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/2/2013 8:04 PM, Sean Kelly wrote:
 It isn't a program bug in this case though. This is essentially an object
 database that lazily maps in chunks of the data store on demand. The objects
 are then used directly from mapped memory without any intermediate loading
 thanks to some dirty tricks played to guarantee vtbl placement in application
 memory across releases. Ridiculously fast and it allows large databases to be
 used efficiently. This backs an accounting system used by large trading
 firms.

Sorry, I misunderstood.
Oct 02 2013
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/3/2013 1:02 AM, Max Samukha wrote:
 That famous prejudice of yours :).

Not just me, and I didn't invent it. It's a "prejudice" used by experienced engineers who build things that, if they fail, kill people. That prejudice is relearned, over and over, by bitter experience.
 As always, it depends. The application can't
 "recover" but it can give the user an opportunity to (partially) recover his
 work. For example, I appreciated the fact that Cubase/Nuendo often continued
 execution after a poorly debugged in-process plugin segfaulted. I do not know
 exactly what cleanup procedure the application executed on the inconsistent
 state but most of the time I was able to recover it completely.

You've got a badly designed program if it relies on that to recover user data.
Oct 03 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/3/2013 2:15 PM, nazriel wrote:
 Music player (as example) do not kill people if they fail.
 Aborting whole music player just because Visualisation plugin had access
 violation is pointless.

How does the music player know the fault is in the plugin and it could be safely continued? It doesn't. It cannot. With a shared address space, it could be anywhere.
 You can't put every use case into the same bag...

I doubt the users would be pleased if continuing running the program resulted in further corruption of the system, including the user's data. Yes, and I've used music players that did that. It sux having to rebuild the music database from backups every time. It doesn't make me think kindly of the player's developers. A properly designed system with user-supplied plugins that needed to recover from plugin failure would put those plugins in a separate process space, so when they crash they cannot affect the rest of the system. Any other scheme is just a bad design, although it may be convenient from a developer cost standpoint to write it that way. And lastly, such badly designed plugin systems are rich vectors for people to insert malware into your system. See ActiveX for an example.
Oct 03 2013
next sibling parent Paulo Pinto <pjmlp progtools.org> writes:
On 04.10.2013 00:38, Walter Bright wrote:
 On 10/3/2013 2:15 PM, nazriel wrote:
 Music player (as example) do not kill people if they fail.
 Aborting whole music player just because Visualisation plugin had access
 violation is pointless.

How does the music player know the fault is in the plugin and it could be safely continued? It doesn't. It cannot. With a shared address space, it could be anywhere.
 You can't put every use case into the same bag...

I doubt the users would be pleased if continuing running the program resulted in further corruption of the system, including the user's data. Yes, and I've used music players that did that. It sux having to rebuild the music database from backups every time. It doesn't make me think kindly of the player's developers. A properly designed system with user-supplied plugins that needed to recover from plugin failure would put those plugins in a separate process space, so when they crash they cannot affect the rest of the system. Any other scheme is just a bad design, although it may be convenient from a developer cost standpoint to write it that way. And lastly, such badly designed plugin systems are rich vectors for people to insert malware into your system. See ActiveX for an example.

This is actually one of the reasons Go guys are so opinated against dynamic linking. I used to complain about it on gonuts forums, but eventually came to realize, that I was a bit spoiled by dynamic loading for plugins and the old UNIX model of processes for plugins is what makes more sense from the security point of view. And it is the trend we are seeing nowadays with the integration of micro-kernel techniques in mainstream OSs. Gatekeeper in Mac OS X/iOS, user space drivers in Windows, FF and Chrome plugin APIs, ... Plugins as dynamic libraries open the door for great customizations, but they open the door for possible instability of the host application and security exploits. -- Paulo
Oct 03 2013
prev sibling next sibling parent Paulo Pinto <pjmlp progtools.org> writes:
On 04.10.2013 01:49, Jonathan M Davis wrote:
 On Friday, October 04, 2013 01:18:31 deadalnix wrote:
 On Thursday, 3 October 2013 at 22:38:18 UTC, Walter Bright wrote:
 On 10/3/2013 2:15 PM, nazriel wrote:
 Music player (as example) do not kill people if they fail.
 Aborting whole music player just because Visualisation plugin
 had access
 violation is pointless.

How does the music player know the fault is in the plugin and it could be safely continued?

Because a music player can ALWAYS safely continue. Worst case scenario, if behave erratically and is killed by user. A car firmware kill people if they behave erratically. The right choice is to kill it if anything look wrong. A media player won't kill anyone.

Just because it won't kill anyone doesn't mean that it's okay for it to continue after it's in a bad state. It could do other nasty things to the system (including corrupt the files that it's operating on). Once a program's in an invalid state, all bets are off. I fully concur with Walter that it's better to kill the program at that point and restart it whether lives are on the line or not. And if that means that the user sees crashes, oh well. They'll complain and the developer will have to fix them, which is exactly what they need to do, because they wouldn't be getting stuff like segfaults or Errors if their code wasn't broken. - Jonathan M Davis

Fully agree. We only got in the sore point of today's industry quality because people got used to have broken applications. Noone is happy driving a car that kind of works, shoes with shoelaces that will only work in nights of full moon, .... Quality should be always a concern, not only when people lives are at stake. -- Paulo
Oct 03 2013
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/3/2013 4:49 PM, Jonathan M Davis wrote:
 Just because it won't kill anyone doesn't mean that it's okay for it to
 continue after it's in a bad state. It could do other nasty things to the
 system (including corrupt the files that it's operating on). Once a program's
 in an invalid state, all bets are off. I fully concur with Walter that it's
 better to kill the program at that point and restart it whether lives are on
 the line or not. And if that means that the user sees crashes, oh well.
 They'll complain and the developer will have to fix them, which is exactly what
 they need to do, because they wouldn't be getting stuff like segfaults or
 Errors if their code wasn't broken.

Exactly. Note that memory corruption can also result in corruption of user data, as I mentioned, and it can ALSO result in corruption of your system. The music player can read and write files, right? Kaboom. I was just talking to Andrei earlier about the bad old MSDOS programming days. There, if you had an errant pointer, it didn't seg fault. It would scramble the operating system tables, and having YOUR HARD DISK SCRAMBLED was a not uncommon experience. Continuing program execution after it failed due to programming bugs is just a bad, bad, bad idea, and it needs to die.
Oct 03 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/3/2013 5:55 PM, Andrej Mitrovic wrote:
 On 10/4/13, Walter Bright <newshound2 digitalmars.com> wrote:
 Continuing program execution after it failed due to programming bugs is just
 a bad, bad, bad idea, and it needs to die.

Then why did you introduce the Error exception type into the language in the first place? I mean why would you let exceptions propagate up the call stack if the state of the program is seriously compromised? Why not just call the system's exit() function? If nobody up the call stack could do anything useful, then there's no point in walking up the call stack. And yet we have Error that does exactly that. What I'm saying is the act of throwing an Error itself is an act of continuing program execution after a serious failure. And here you are arguing against it.

Error exceptions are not necessarily program bugs. They are non-recoverable errors, which is not the same thing.
Oct 03 2013
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-10-04 02:08, H. S. Teoh wrote:

 Reminds me of a GUI app I tried years ago, that suffered from some kind
 of memory corruption bug. Every now and then it would segfault due to
 hitting the corruption... one time, it *didn't* segfault, but continued
 merrily on and corrupted all of my data -- worth many hours of work --
 all without showing any signs of problems, and then out of habit I saved
 the file I was working on, and it barged ahead and wrote garbage all
 over my last good copy of the data. :-(

I have had the same experience. We had to use an application in school that was notorious to crash and corrupt your files. I kept ten different save files, cycled through them when I saved. When it did crash it corrupt not just the file I was working on but five other of my ten save files. Of course, these we're the five latest files and the other were too old. That really sucked. -- /Jacob Carlborg
Oct 03 2013
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/3/2013 11:46 PM, Jacob Carlborg wrote:
 On 2013-10-04 02:08, H. S. Teoh wrote:

 Reminds me of a GUI app I tried years ago, that suffered from some kind
 of memory corruption bug. Every now and then it would segfault due to
 hitting the corruption... one time, it *didn't* segfault, but continued
 merrily on and corrupted all of my data -- worth many hours of work --
 all without showing any signs of problems, and then out of habit I saved
 the file I was working on, and it barged ahead and wrote garbage all
 over my last good copy of the data. :-(

I have had the same experience. We had to use an application in school that was notorious to crash and corrupt your files. I kept ten different save files, cycled through them when I saved. When it did crash it corrupt not just the file I was working on but five other of my ten save files. Of course, these we're the five latest files and the other were too old. That really sucked.

I think it's pretty clear that the solution to saving a user's work-in-progress is to have the application actually save the work-in-progress at regular intervals, not try to save it after it has crashed.
Oct 04 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-10-04 09:40, Walter Bright wrote:

 I think it's pretty clear that the solution to saving a user's
 work-in-progress is to have the application actually save the
 work-in-progress at regular intervals, not try to save it after it has
 crashed.

Yes, but I don't know why it touched five of my save files. I can understand that it corrupted one, but not five. -- /Jacob Carlborg
Oct 04 2013
parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/4/2013 1:50 AM, Jacob Carlborg wrote:
 On 2013-10-04 09:40, Walter Bright wrote:

 I think it's pretty clear that the solution to saving a user's
 work-in-progress is to have the application actually save the
 work-in-progress at regular intervals, not try to save it after it has
 crashed.

Yes, but I don't know why it touched five of my save files. I can understand that it corrupted one, but not five.

Because its internal logic and code got scrambled, it can exhibit any behavior. That's the point.
Oct 04 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 10/04/2013 01:18 AM, deadalnix wrote:
 A media player won't kill anyone.

I'm not sure. Excerpt from the iTunes EULA: "You also agree that you will not use these products for any purposes prohibited by United States law, including, without limitation, the development, design, manufacture or production of nuclear, missiles, or chemical or biological weapons." http://www.apple.com/legal/internet-services/itunes/appstore/dev/stdeula/
Oct 31 2013
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-10-31 23:20, Timon Gehr wrote:

 I'm not sure. Excerpt from the iTunes EULA:

 "You also agree that you will not use these products for any purposes
 prohibited by United States law, including, without limitation, the
 development, design, manufacture or production of nuclear, missiles, or
 chemical or biological weapons."

 http://www.apple.com/legal/internet-services/itunes/appstore/dev/stdeula/

Haha :) -- /Jacob Carlborg
Nov 01 2013
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-11-01 12:56, Wyatt wrote:

 I would classify forcing someone to use iTunes as "psychological
 warfare".  Unfortunately, that's not covered by the EULA. ;)

Then you're good to go :) -- /Jacob Carlborg
Nov 01 2013
prev sibling parent Martin Nowak <code dawg.eu> writes:
On 10/02/2013 12:37 AM, Jonathan M Davis wrote:
 As I understand it, the problem is that there isn't really another mechanism
 to do what druntime is using signals for. So, we're between a bit of a rock
 and a hard place. Ideally though, we would find a way to do it without using
 signals.

 - Jonathan M Davis

What we need is pthread_suspend and the ability to determine the stack top of the suspended thread. That would also allow for some nice unification of core.thread. I already have that on my TODO list, low prio though. I think I saw a solution to this in some other GC (V8 maybe?).
Oct 01 2013
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Tuesday, 1 October 2013 at 18:16:27 UTC, Jacob Carlborg wrote:
 On 2013-10-01 13:19, PauloPinto wrote:

 I just remember that you also have the added problem that 
 signal
 handlers are very limited in what you are allowed to do, with 
 the set of
 restrictions and guarantees not being portable across all 
 POSIX systems.

 Specially the tricks of notifying the application a signal has 
 happened,
 after signal returns and the whole story of redoing 
 interrupted system
 calls.

druntime already handles SIGSEGV signals, at least for Linux: https://github.com/D-Programming-Language/druntime/blob/master/src/etc/linux/memoryerror.d

Is this feature working as built-in or by demand?
Oct 01 2013
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Tuesday, 1 October 2013 at 19:55:17 UTC, monarch_dodra wrote:
 On Tuesday, 1 October 2013 at 03:58:04 UTC, Nick Sabalausky 
 wrote:
 You know, this sounds like something that really should fall 
 squarely in
 the category of "do the right thing by default". Is there any 
 reason
 druntime can't be made to handle this better by default?

Well, arguably, a segfault is a catastrophic error, even more serious than an assert.

In linux assert(0) causes a segfault. And the fact that detected by OS memory error is sigfault at linux and exception on windows really hurts portability.
 I'm not sure what "the right thing" would even be, apart from 
 dying right there and then...?

 Even just throwing an error could be problematic (AFAIK).

Druntime can catch SIGINT and throw the exception. This means that D runtime can be easily broken by silly C code which uses its own signal handlers. I didn't tested, but believe this is already the case with respect to SIGUSR1 and SIGUSR2 which are used by druntime, so any simple code hijacking the signals can break runtime. Linux signals handlers as error mechanism is a complete disaster.
Oct 01 2013
prev sibling next sibling parent Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> writes:
On Tue, 01 Oct 2013 21:55:16 +0200
"monarch_dodra" <monarchdodra gmail.com> wrote:

 On Tuesday, 1 October 2013 at 03:58:04 UTC, Nick Sabalausky wrote:
 You know, this sounds like something that really should fall 
 squarely in
 the category of "do the right thing by default". Is there any 
 reason
 druntime can't be made to handle this better by default?

Well, arguably, a segfault is a catastrophic error, even more serious than an assert. I'm not sure what "the right thing" would even be, apart from dying right there and then...? Even just throwing an error could be problematic (AFAIK).

I'm not talking about segfaults, I'm talking about the OP's issue of a mere Ctrl-C causing cleanup code to not get executed.
Oct 01 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 1 October 2013 at 19:55:17 UTC, monarch_dodra wrote:
 On Tuesday, 1 October 2013 at 03:58:04 UTC, Nick Sabalausky 
 wrote:
 You know, this sounds like something that really should fall 
 squarely in
 the category of "do the right thing by default". Is there any 
 reason
 druntime can't be made to handle this better by default?

Well, arguably, a segfault is a catastrophic error, even more serious than an assert.

It shouldn't in a language that have nullable type as default.
Oct 01 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 1 October 2013 at 20:06:46 UTC, Maxim Fomin wrote:
 On Tuesday, 1 October 2013 at 18:16:27 UTC, Jacob Carlborg 
 wrote:
 On 2013-10-01 13:19, PauloPinto wrote:

 I just remember that you also have the added problem that 
 signal
 handlers are very limited in what you are allowed to do, with 
 the set of
 restrictions and guarantees not being portable across all 
 POSIX systems.

 Specially the tricks of notifying the application a signal 
 has happened,
 after signal returns and the whole story of redoing 
 interrupted system
 calls.

druntime already handles SIGSEGV signals, at least for Linux: https://github.com/D-Programming-Language/druntime/blob/master/src/etc/linux/memoryerror.d

Is this feature working as built-in or by demand?

By demand. Call registerMemoryErrorHandler to enable it and deregisterMemoryErrorHandler to rollback.
Oct 01 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 1 October 2013 at 20:42:59 UTC, Nick Sabalausky wrote:
 I'm not talking about segfaults, I'm talking about the OP's 
 issue of
 a mere Ctrl-C causing cleanup code to not get executed.

The question discussed here is how to throw an exception when a signal is received. It doesn't really matter if this is because of a segfault or because of ctrl+c . As this work as been done for segfault, it make sense to refers to it.
Oct 01 2013
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, October 01, 2013 23:17:01 deadalnix wrote:
 On Tuesday, 1 October 2013 at 19:55:17 UTC, monarch_dodra wrote:
 On Tuesday, 1 October 2013 at 03:58:04 UTC, Nick Sabalausky
 
 wrote:
 You know, this sounds like something that really should fall
 squarely in
 the category of "do the right thing by default". Is there any
 reason
 druntime can't be made to handle this better by default?

Well, arguably, a segfault is a catastrophic error, even more serious than an assert.

It shouldn't in a language that have nullable type as default.

I don't see why that's relevant. If you hit a segfault - regardless of whether it's because of a memory corruption or a null pointer or whatever - it's an error that should terminate your program. If we checked for null pointers and threw NullPointerError instead of segfaulting, it would be no different except that it would be an Error being thrown. Both it and segfaults are supposed to kill your program without doing cleanup. - Jonathan M Davis
Oct 01 2013
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, October 01, 2013 22:16:04 Maxim Fomin wrote:
 Druntime can catch SIGINT and throw the exception. This means
 that D runtime can be easily broken by silly C code which uses
 its own signal handlers. I didn't tested, but believe this is
 already the case with respect to SIGUSR1 and SIGUSR2 which are
 used by druntime, so any simple code hijacking the signals can
 break runtime. Linux signals handlers as error mechanism is a
 complete disaster.

As I understand it, the problem is that there isn't really another mechanism to do what druntime is using signals for. So, we're between a bit of a rock and a hard place. Ideally though, we would find a way to do it without using signals. - Jonathan M Davis
Oct 01 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 1 October 2013 at 23:32:38 UTC, Paulo Pinto wrote:
 s/Linux/UNIX/g

The described technique use some OS specific features. It can be adapted to OSX as far as I know, but POSIX do not guarantee to have all required features to implement this.
Oct 01 2013
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Oct 01, 2013 at 06:44:05PM +0200, deadalnix wrote:
 On Tuesday, 1 October 2013 at 14:53:24 UTC, H. S. Teoh wrote:
On Tue, Oct 01, 2013 at 02:06:12PM +0200, deadalnix wrote:
On Monday, 30 September 2013 at 22:55:22 UTC, H. S. Teoh wrote:
On Mon, Sep 30, 2013 at 08:44:36PM +0200, deadalnix wrote:
On Monday, 30 September 2013 at 02:13:47 UTC, H. S. Teoh
wrote:
Well, ctrl-C can be handled, so the way I'd do it is to set up a
signal handler for SIGINT and have it write something to a
self-pipe read by the event handler, then the event handler can
throw an Exception (which should cause dtors to run as the stack
unwinds).

No you can't. But you somehow can, if you want to use some black magic : http://www.deadalnix.me/2012/03/24/get-an-exception-from-a-segfault-on-linux-x86-and-x86_64-using-some-black-magic/

We were talking about SIGINT, not SIGSEGV.

That isn't relevant here.

Huh? The OP was talking about cleaning up after ctrl-C, not after a segfault. I already know you can't throw exceptions from a segfault (except with heavy trickery, and yes I remember the post you linked and I know how it works). SIGINT is different because it can be handled, and the signal handler can just write a byte to a pipe read by the main event loop, outside of signal handler context.

The signal handler cannot throw exception. If you want to do so, you need the same scafolding.

I know that. :) All I said was that the signal handler writes a byte to a pipe, which gets read by the event loop (OUTSIDE of signal handler context), and then the event loop does the throw. Now, having *druntime* throw an exception upon ctrl-C is something totally different, and yes it will require some kind of scaffolding/hack to make it work, 'cos the exception must propagate outside of signal handler context. T -- Notwithstanding the eloquent discontent that you have just respectfully expressed at length against my verbal capabilities, I am afraid that I must unfortunately bring it to your attention that I am, in fact, NOT verbose.
Oct 01 2013
prev sibling next sibling parent "qznc" <qznc web.de> writes:
On Tuesday, 1 October 2013 at 11:48:51 UTC, w0rp wrote:
 This is a really good question, I think! Python has a 
 KeyboardInterrupt exception for this purpose. Should we perhap 
 try something similar? Perhaps as a library solution? I think a 
 function like some_module.registerInterruptExceptions() would 
 be cool to have. If someone knows a way to do that, that would 
 be cool. I'm looking at deadalnix...

I don't like where this is headed. Converting signals into exceptions is a bad idea. In a multithreaded program, which thread should get the exception thrown? The main thread? Every thread? What if main already terminated? The InterruptException must be anticipated in lots of places and most people will forget about it. Basically, the issues are very similar to killing threads [0]. Throwing exception anywhere without any relation to the code at that point is a recipe for disaster. [0] http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
Oct 02 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 2 October 2013 at 09:16:44 UTC, qznc wrote:
 On Tuesday, 1 October 2013 at 11:48:51 UTC, w0rp wrote:
 This is a really good question, I think! Python has a 
 KeyboardInterrupt exception for this purpose. Should we perhap 
 try something similar? Perhaps as a library solution? I think 
 a function like some_module.registerInterruptExceptions() 
 would be cool to have. If someone knows a way to do that, that 
 would be cool. I'm looking at deadalnix...

I don't like where this is headed. Converting signals into exceptions is a bad idea. In a multithreaded program, which thread should get the exception thrown? The main thread? Every thread? What if main already terminated? The InterruptException must be anticipated in lots of places and most people will forget about it. Basically, the issues are very similar to killing threads [0]. Throwing exception anywhere without any relation to the code at that point is a recipe for disaster. [0] http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html

The whole point of Exception is that you care about them only if you know how to handle them. Exception are the way a piece of code can say "Fuck that shit, I have no clue how to proceed with that"
Oct 02 2013
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Oct 1, 2013, at 10:12 PM, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:
=20
 Now, having *druntime* throw an exception upon ctrl-C is something
 totally different, and yes it will require some kind of =

 to make it work, 'cos the exception must propagate outside of signal
 handler context.

I believe the way this currently works is by dynamically modifying code = at the point the SEGV occurred, which first patches up the code that was = modified and then throws. But if the SEGV was inside a system call, you = could be in serious trouble, since that code isn't exception safe.=
Oct 02 2013
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Oct 02, 2013 at 10:36:08AM -0700, Sean Kelly wrote:
 On Oct 1, 2013, at 10:12 PM, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:
 
 Now, having *druntime* throw an exception upon ctrl-C is something
 totally different, and yes it will require some kind of scaffolding/hack
 to make it work, 'cos the exception must propagate outside of signal
 handler context.

I believe the way this currently works is [...]

Wait, this *currently* works?!
 [...] by dynamically modifying code at the point the SEGV occurred,
 which first patches up the code that was modified and then throws.

I thought the hack posted in the thread deadalnix linked to was to have the signal handler "corrupt" the stack -- i.e., modify it so that the return address is redirected to a segfault handler. Thus, as soon as the signal handler returns (and leaves signal handler context), instead of returning to its original caller it "returns" to the segfault handler instead, which can then set things up properly for stack unwinding and throw an exception (or Error as the case may be). Though, granted, since segfaults can happen anywhere, including inside nothrow functions, there is no guarantee dtors will run or things will properly cleanup, etc.. All the usual caveat emptors apply.
 But if the SEGV was inside a system call, you could be in serious
 trouble, since that code isn't exception safe.

Well, SEGV itself is already serious trouble. :P I don't think there's any safe way to "recover" from a SEGV, since it indicates that something has gone horribly wrong in a way the code can't handle. I think the OP's original point was how to ensure certain cleanups always ran (e.g. switch terminal back to normal teletype mode when the program has been running in ncurses mode). Well, there is no guarantee that it will run, due to the nature of segfaults, but assuming that the dtors concerned are high enough up the call stack to not be affected by Errors bypassing dtors due to being inside nothrow functions, it *should* work in the general case. Obviously, the program should never try to catch a SegfaultError and attempt to "recover" from it, since the program is already horribly screwed up by that point. T -- It said to install Windows 2000 or better, so I installed Linux instead.
Oct 02 2013
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Oct 2, 2013, at 3:34 AM, Paulo Pinto <pjmlp progtools.org> wrote:

 I don't do UNIX system programming at C level since 2002, but my POSIX =

behaviors and OS specific extensions. Posix is super portable largely because the spec is very loose. Not = many functions actually have to be declared, and of those that must be = declared, some can actually return an error when called that indicates = they aren't implemented. And what's allowed in signal handlers, for = example, is very limited as well, for similar reasons. This is one area = where Windows really did things right. As Don has noted in the past, = SEH is really fantastic. I still do systems level C programming as my = primary job responsibility, and my dislike of signals is nearly = boundless at this point. Even for things that make sense like SIGCHLD, = the limited options available within signal handlers make actually doing = anything useful surprisingly hard. I really wish Posix routines were = required to use critical sections to delay signals until handling them = wouldn't break anything.=
Oct 02 2013
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Oct 1, 2013, at 7:30 PM, Walter Bright <newshound2 digitalmars.com> =
wrote:

 On 10/1/2013 3:37 PM, Jonathan M Davis wrote:
 On Tuesday, October 01, 2013 23:17:01 deadalnix wrote:
 It shouldn't in a language that have nullable type as default.

I don't see why that's relevant. If you hit a segfault - regardless =


 it's because of a memory corruption or a null pointer or whatever - =


 error that should terminate your program. If we checked for null =


 threw NullPointerError instead of segfaulting, it would be no =


 that it would be an Error being thrown. Both it and segfaults are =


 kill your program without doing cleanup.

Right. A null pointer dereference is a logic bug in your program, and =

=20
 If there's one notion I'd like to terminate with prejudice, it's the =

I worked on a system whose design was specifically built around trapping = and recovering from segfaults (great design, and sadly, patented). = Things like this are one of the primary reasons to use a systems = programming language. So while I agree in the general sense, I don't = think it's appropriate for the language to make a hard and fast = assertion here. I think we should choose a reasonable, safe default, = but make it overridable. That's pretty much the design philosophy of = Druntime.=
Oct 02 2013
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Oct 1, 2013, at 1:16 PM, Maxim Fomin <maxim maxim-fomin.ru> wrote:
=20
 Druntime can catch SIGINT and throw the exception. This means that D =

handlers. I didn't tested, but believe this is already the case with = respect to SIGUSR1 and SIGUSR2 which are used by druntime, so any simple = code hijacking the signals can break runtime. Linux signals handlers as = error mechanism is a complete disaster. Unix signal handlers in general are a complete disaster. The core idea = is good, but the Posix requirements surrounding them are so loose as to = render them nearly unusable. I wasn't aware of pthread_suspend and it appears to be quite new. Does = anyone know if it's implemented in Linux yet? A StackThreads discussion = I found from a few years ago said it isn't, but a lot can change in a = few years. I would absolutely love to do away with using signals for = coordinating garbage collection wherever possible.=
Oct 02 2013
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Oct 2, 2013, at 11:08 AM, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:

 On Wed, Oct 02, 2013 at 10:36:08AM -0700, Sean Kelly wrote:
 On Oct 1, 2013, at 10:12 PM, H. S. Teoh <hsteoh quickfur.ath.cx> =


=20
 Now, having *druntime* throw an exception upon ctrl-C is something
 totally different, and yes it will require some kind of =



 to make it work, 'cos the exception must propagate outside of signal
 handler context.

I believe the way this currently works is [...]

Wait, this *currently* works?!

Oops. I thought the hack for this was integrated ages ago, but I don't = see it.
 [...] by dynamically modifying code at the point the SEGV occurred,
 which first patches up the code that was modified and then throws.

I thought the hack posted in the thread deadalnix linked to was to =

 the signal handler "corrupt" the stack -- i.e., modify it so that the
 return address is redirected to a segfault handler. Thus, as soon as =

 signal handler returns (and leaves signal handler context), instead of
 returning to its original caller it "returns" to the segfault handler
 instead, which can then set things up properly for stack unwinding and
 throw an exception (or Error as the case may be).

Yes.
 But if the SEGV was inside a system call, you could be in serious
 trouble, since that code isn't exception safe.

Well, SEGV itself is already serious trouble. :P I don't think =

 any safe way to "recover" from a SEGV, since it indicates that =

 has gone horribly wrong in a way the code can't handle.

It depends why and where, really. See my reply to Walter.
 I think the OP's original point was how to ensure certain cleanups
 always ran (e.g. switch terminal back to normal teletype mode when the
 program has been running in ncurses mode). Well, there is no guarantee
 that it will run, due to the nature of segfaults, but assuming that =

 dtors concerned are high enough up the call stack to not be affected =

 Errors bypassing dtors due to being inside nothrow functions, it
 *should* work in the general case. Obviously, the program should never
 try to catch a SegfaultError and attempt to "recover" from it, since =

 program is already horribly screwed up by that point.

Yes, trying to recover from a thrown Error is rarely a good idea. About = the only one I'd consider trying to recover from is an OutOfMemoryError, = and even then I'd be more inclined to assume a memory leak and just let = the process die and restart.=
Oct 02 2013
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 3 October 2013 at 00:25:26 UTC, Walter Bright wrote:
 Although I haven't seen the system you describe, I'm very 
 skeptical that it found the solution to the problem of a 
 program successfully continuing after it has crashed due to 
 program bugs. I remain firmly convinced that that is an utterly 
 wrong and doomed approach to the problem of reliability.

Segfaults aren't necessarily bugs... though I'm not sure if a userspace handler can do much about it. But from a kernel perspective, they can be generated by page faults too, which can be successfully handled by loading the requested memory block (e.g. from a swap file) and then retrying the operation, or copying the page into a writable location and mapping that in; hardware assisted copy-on-write. I've never tried to do this in a unix program so I don't know how much you can do, but presumably Sean's example did something along these lines, so it would be by design rather than bugs.
Oct 02 2013
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Oct 2, 2013, at 5:25 PM, Walter Bright <newshound2 digitalmars.com> wrote=
:
=20
 On 10/2/2013 10:10 AM, Sean Kelly wrote:
 If there's one notion I'd like to terminate with prejudice, it's the not=



 that a running program can "recover" from bugs in itself.

I worked on a system whose design was specifically built around trapping a=


 recovering from segfaults (great design, and sadly, patented).  Things li=


 this are one of the primary reasons to use a systems programming language=


 So while I agree in the general sense, I don't think it's appropriate for=


 language to make a hard and fast assertion here.  I think we should choos=


 reasonable, safe default, but make it overridable.  That's pretty much th=


 design philosophy of Druntime.

D being a systems programming language, you can pursue whatever design you=

=20
 Although I haven't seen the system you describe, I'm very skeptical that i=

er it has crashed due to program bugs. I remain firmly convinced that that i= s an utterly wrong and doomed approach to the problem of reliability. It isn't a program bug in this case though. This is essentially an object da= tabase that lazily maps in chunks of the data store on demand. The objects a= re then used directly from mapped memory without any intermediate loading th= anks to some dirty tricks played to guarantee vtbl placement in application m= emory across releases. Ridiculously fast and it allows large databases to be= used efficiently. This backs an accounting system used by large trading fir= ms. In any case, my point remains that some features like this can be part of a g= ood design in rare cases. So systems languages shouldn't flat out prevent th= em, but rather put an "experts only" label on there somewhere.=20=
Oct 02 2013
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Oct 2, 2013, at 6:15 PM, "Adam D. Ruppe" <destructionator gmail.com> wrot=
e:
=20
 On Thursday, 3 October 2013 at 00:25:26 UTC, Walter Bright wrote:
 Although I haven't seen the system you describe, I'm very skeptical that i=


er it has crashed due to program bugs. I remain firmly convinced that that i= s an utterly wrong and doomed approach to the problem of reliability.
=20
 Segfaults aren't necessarily bugs... though I'm not sure if a userspace ha=

ated by page faults too, which can be successfully handled by loading the re= quested memory block (e.g. from a swap file) and then retrying the operation= , or copying the page into a writable location and mapping that in; hardware= assisted copy-on-write.
=20
 I've never tried to do this in a unix program so I don't know how much you=

t would be by design rather than bugs. This exactly. It goes a bit beyond what Posix allows in signal handlers, but= it works just fine on this particular system.=20=
Oct 02 2013
prev sibling next sibling parent "Max Samukha" <maxsamukha gmail.com> writes:
On Wednesday, 2 October 2013 at 02:30:42 UTC, Walter Bright wrote:

 Right. A null pointer dereference is a logic bug in your 
 program, and hence the program needs to stop immediately, not 
 execute "cleanup" code.

 If there's one notion I'd like to terminate with prejudice, 
 it's the notion that a running program can "recover" from bugs 
 in itself.

That famous prejudice of yours :). As always, it depends. The application can't "recover" but it can give the user an opportunity to (partially) recover his work. For example, I appreciated the fact that Cubase/Nuendo often continued execution after a poorly debugged in-process plugin segfaulted. I do not know exactly what cleanup procedure the application executed on the inconsistent state but most of the time I was able to recover it completely.
Oct 03 2013
prev sibling next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Thursday, 3 October 2013 at 08:02:17 UTC, Max Samukha wrote:
 On Wednesday, 2 October 2013 at 02:30:42 UTC, Walter Bright 
 wrote:

 Right. A null pointer dereference is a logic bug in your 
 program, and hence the program needs to stop immediately, not 
 execute "cleanup" code.

 If there's one notion I'd like to terminate with prejudice, 
 it's the notion that a running program can "recover" from bugs 
 in itself.

That famous prejudice of yours :). As always, it depends. The application can't "recover" but it can give the user an opportunity to (partially) recover his work. For example, I appreciated the fact that Cubase/Nuendo often continued execution after a poorly debugged in-process plugin segfaulted. I do not know exactly what cleanup procedure the application executed on the inconsistent state but most of the time I was able to recover it completely.

This. I agree that in a purist sense, a broken program is broken, end of. However, in the real world it's a balance of risk.
Oct 03 2013
prev sibling next sibling parent "nazriel" <spam dzfl.pl> writes:
On Thursday, 3 October 2013 at 20:54:00 UTC, Walter Bright wrote:
 On 10/3/2013 1:02 AM, Max Samukha wrote:
 That famous prejudice of yours :).

Not just me, and I didn't invent it. It's a "prejudice" used by experienced engineers who build things that, if they fail, kill people. That prejudice is relearned, over and over, by bitter experience.

Music player (as example) do not kill people if they fail. Aborting whole music player just because Visualisation plugin had access violation is pointless. You can't put every use case into the same bag...
 As always, it depends. The application can't
 "recover" but it can give the user an opportunity to 
 (partially) recover his
 work. For example, I appreciated the fact that Cubase/Nuendo 
 often continued
 execution after a poorly debugged in-process plugin 
 segfaulted. I do not know
 exactly what cleanup procedure the application executed on the 
 inconsistent
 state but most of the time I was able to recover it completely.

You've got a badly designed program if it relies on that to recover user data.

Oct 03 2013
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Oct 03, 2013 at 11:15:11PM +0200, nazriel wrote:
 On Thursday, 3 October 2013 at 20:54:00 UTC, Walter Bright wrote:
On 10/3/2013 1:02 AM, Max Samukha wrote:
That famous prejudice of yours :).

Not just me, and I didn't invent it. It's a "prejudice" used by experienced engineers who build things that, if they fail, kill people. That prejudice is relearned, over and over, by bitter experience.

Music player (as example) do not kill people if they fail. Aborting whole music player just because Visualisation plugin had access violation is pointless.

Run the plugin in a sandbox. T -- INTEL = Only half of "intelligence".
Oct 03 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 3 October 2013 at 22:38:18 UTC, Walter Bright wrote:
 On 10/3/2013 2:15 PM, nazriel wrote:
 Music player (as example) do not kill people if they fail.
 Aborting whole music player just because Visualisation plugin 
 had access
 violation is pointless.

How does the music player know the fault is in the plugin and it could be safely continued?

Because a music player can ALWAYS safely continue. Worst case scenario, if behave erratically and is killed by user. A car firmware kill people if they behave erratically. The right choice is to kill it if anything look wrong. A media player won't kill anyone.
 A properly designed system with user-supplied plugins that 
 needed to recover from plugin failure would put those plugins 
 in a separate process space, so when they crash they cannot 
 affect the rest of the system. Any other scheme is just a bad 
 design, although it may be convenient from a developer cost 
 standpoint to write it that way.

Yes. Anything is a cost benefit tradeoff. The cost of developing a sandboxing solution is way higher than doing some recovery that will fail in 1% of the case in a way that won't kill anyone. And unless phobos get a sandboxing solution builtin, the argument will stand.
Oct 03 2013
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 3 October 2013 at 23:18:32 UTC, deadalnix wrote:
 And unless phobos get a sandboxing solution builtin, the 
 argument will stand.

pipeProcess is an ok starting point. (Though when I tried to use it recently, the fact that it didn't support async i/o on Windows meant I had to roll my own anyway...) but if you spawned the plugin as a process and then just sent/received messages through the pipes it isn't too hard to make an application out of it, especially with an rpc library too.
Oct 03 2013
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, October 04, 2013 01:18:31 deadalnix wrote:
 On Thursday, 3 October 2013 at 22:38:18 UTC, Walter Bright wrote:
 On 10/3/2013 2:15 PM, nazriel wrote:
 Music player (as example) do not kill people if they fail.
 Aborting whole music player just because Visualisation plugin
 had access
 violation is pointless.

How does the music player know the fault is in the plugin and it could be safely continued?

Because a music player can ALWAYS safely continue. Worst case scenario, if behave erratically and is killed by user. A car firmware kill people if they behave erratically. The right choice is to kill it if anything look wrong. A media player won't kill anyone.

Just because it won't kill anyone doesn't mean that it's okay for it to continue after it's in a bad state. It could do other nasty things to the system (including corrupt the files that it's operating on). Once a program's in an invalid state, all bets are off. I fully concur with Walter that it's better to kill the program at that point and restart it whether lives are on the line or not. And if that means that the user sees crashes, oh well. They'll complain and the developer will have to fix them, which is exactly what they need to do, because they wouldn't be getting stuff like segfaults or Errors if their code wasn't broken. - Jonathan M Davis
Oct 03 2013
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Oct 03, 2013 at 07:49:16PM -0400, Jonathan M Davis wrote:
 On Friday, October 04, 2013 01:18:31 deadalnix wrote:
 On Thursday, 3 October 2013 at 22:38:18 UTC, Walter Bright wrote:
 On 10/3/2013 2:15 PM, nazriel wrote:
 Music player (as example) do not kill people if they fail.
 Aborting whole music player just because Visualisation plugin
 had access violation is pointless.

How does the music player know the fault is in the plugin and it could be safely continued?

Because a music player can ALWAYS safely continue. Worst case scenario, if behave erratically and is killed by user. A car firmware kill people if they behave erratically. The right choice is to kill it if anything look wrong. A media player won't kill anyone.

Just because it won't kill anyone doesn't mean that it's okay for it to continue after it's in a bad state. It could do other nasty things to the system (including corrupt the files that it's operating on). Once a program's in an invalid state, all bets are off. I fully concur with Walter that it's better to kill the program at that point and restart it whether lives are on the line or not. And if that means that the user sees crashes, oh well. They'll complain and the developer will have to fix them, which is exactly what they need to do, because they wouldn't be getting stuff like segfaults or Errors if their code wasn't broken.

Reminds me of a GUI app I tried years ago, that suffered from some kind of memory corruption bug. Every now and then it would segfault due to hitting the corruption... one time, it *didn't* segfault, but continued merrily on and corrupted all of my data -- worth many hours of work -- all without showing any signs of problems, and then out of habit I saved the file I was working on, and it barged ahead and wrote garbage all over my last good copy of the data. :-( Now, I don't think it had segfault recovery, but even without, it was already bad enough. I don't think I ever want to find out what that program would've done if it came *with* segfault recovery... (think about all those times it crashed *before* the bad data got saved into the file.) T -- Never ascribe to malice that which is adequately explained by incompetence. -- Napoleon Bonaparte
Oct 03 2013
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Oct 03, 2013 at 05:04:02PM -0700, Walter Bright wrote:
 On 10/3/2013 4:49 PM, Jonathan M Davis wrote:
Just because it won't kill anyone doesn't mean that it's okay for it
to continue after it's in a bad state. It could do other nasty things
to the system (including corrupt the files that it's operating on).
Once a program's in an invalid state, all bets are off. I fully
concur with Walter that it's better to kill the program at that point
and restart it whether lives are on the line or not. And if that
means that the user sees crashes, oh well.  They'll complain and the
developer will have to fix them, which is exactly what they need to
do, because they wouldn't be getting stuff like segfaults or Errors
if their code wasn't broken.

Exactly. Note that memory corruption can also result in corruption of user data, as I mentioned, and it can ALSO result in corruption of your system. The music player can read and write files, right? Kaboom. I was just talking to Andrei earlier about the bad old MSDOS programming days. There, if you had an errant pointer, it didn't seg fault. It would scramble the operating system tables, and having YOUR HARD DISK SCRAMBLED was a not uncommon experience.

Ah yes, those were the days when you *always* kept a full backup of a fully-working snapshot of your OS and dev environment on a separate floppy, so that when your program inevitably crashed / destroyed the OS, you could power off and reboot from the good copy (and promptly make another copy thereafter, in order to not also destroy the last good disk!). Hitting reset / power cycling several times an hour was pretty common, since the most trivial of bugs easily caused the system to hang, or get stuck in graphics mode with no way to (easily) switch it back, or lock up the keyboard somehow, or do any number of other erratic things. Write to a wrong memory address (e.g., dereference a wrong pointer), and boom, you just broke DOS in a subtle way that only shows up the next time you write to a file. Write to another wrong memory address, and boom, one of DOS's core routines got overwritten, now disk I/O doesn't work, or DOS just hangs and won't respond to anything. Jump to an invalid func ptr with the wrong value, and boom, you just entered the DOS FORMAT routine. Bye bye sweet data, it was nice knowing you.
 Continuing program execution after it failed due to programming bugs
 is just a bad, bad, bad idea, and it needs to die.

Heh, my Perl script actually picked a vaguely relevant signature line on its own this time, without manual intervention. :-P T -- If you want to solve a problem, you need to address its root cause, not just its symptoms. Otherwise it's like treating cancer with Tylenol...
Oct 03 2013
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Oct 3, 2013, at 4:49 PM, Jonathan M Davis <jmdavisProg gmx.com> =
wrote:
=20
 Just because it won't kill anyone doesn't mean that it's okay for it =

 continue after it's in a bad state. It could do other nasty things to =

 system (including corrupt the files that it's operating on). Once a =

 in an invalid state, all bets are off. I fully concur with Walter that =

 better to kill the program at that point and restart it whether lives =

 the line or not. And if that means that the user sees crashes, oh =

 They'll complain and the developer will have to fix them, which is =

 they need to do, because they wouldn't be getting stuff like segfaults =

 Errors if their code wasn't broken.

I'm inclined to agree. However, in this case the user will need some = method to remove the broken plugin or the app will be perpetually = broken. It wouldn't surprise me if the original motivation for trying = to withstand failures was a bad decision motivated by something like = this, and at some point it was erroneously considered a feature. I'd = prefer to be notified that a crash was likely caused by a bad plugin and = given the option to restart in "safe" mode, though.=
Oct 03 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 10/4/13, Walter Bright <newshound2 digitalmars.com> wrote:
 Continuing program execution after it failed due to programming bugs is just
 a bad, bad, bad idea, and it needs to die.

Then why did you introduce the Error exception type into the language in the first place? I mean why would you let exceptions propagate up the call stack if the state of the program is seriously compromised? Why not just call the system's exit() function? If nobody up the call stack could do anything useful, then there's no point in walking up the call stack. And yet we have Error that does exactly that. What I'm saying is the act of throwing an Error itself is an act of continuing program execution after a serious failure. And here you are arguing against it.
Oct 03 2013
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, October 04, 2013 02:55:36 Andrej Mitrovic wrote:
 On 10/4/13, Walter Bright <newshound2 digitalmars.com> wrote:
 Continuing program execution after it failed due to programming bugs is
 just a bad, bad, bad idea, and it needs to die.

Then why did you introduce the Error exception type into the language in the first place? I mean why would you let exceptions propagate up the call stack if the state of the program is seriously compromised? Why not just call the system's exit() function? If nobody up the call stack could do anything useful, then there's no point in walking up the call stack. And yet we have Error that does exactly that. What I'm saying is the act of throwing an Error itself is an act of continuing program execution after a serious failure. And here you are arguing against it.

I've actually been wondering about that too. The only case I can think of where catching an Error and continuing _might_ make sense would be with OutOfMemoryError if you caught it right after it was thrown and then did something differently based on the fact that you'd run out of memory. But pretty much all other Errors are outright programming bugs, and all you really need is the stacktrace. Unwinding the stack (even with skipping destructors, finally blocks, etc.) seems extraneous at that point. - Jonathan M Davis
Oct 03 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 9/30/13, Adam D. Ruppe <destructionator gmail.com> wrote:
 Is there anything we can do to automatically clean up if the user
 hits ctrl+c on Linux?

What's interesting is I just ran into this SEH enum in druntime for win32 by chance: CONTROL_C_EXIT But there's no equivalent for linux. Tough luck. :)
Oct 05 2013
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Oct 5, 2013, at 4:09 PM, Andrej Mitrovic <andrej.mitrovich gmail.com> wro=
te:
=20
 On 9/30/13, Adam D. Ruppe <destructionator gmail.com> wrote:
 Is there anything we can do to automatically clean up if the user
 hits ctrl+c on Linux?

What's interesting is I just ran into this SEH enum in druntime for win32 by chance: CONTROL_C_EXIT =20 But there's no equivalent for linux.

You need to trap SIGINT. But then you're stuck in a signal handler and so ca= n't do much to clean up.=20=
Oct 05 2013
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sunday, 6 October 2013 at 02:20:29 UTC, Sean Kelly wrote:
 You need to trap SIGINT. But then you're stuck in a signal 
 handler and so can't do much to clean up.

yeah, what I decided to do was to just set a global variable when the signal arrives and then I checked it on each iteration of my main event loop. Alas it isn't as generic as I was hoping, but at least it works for me.
Oct 05 2013
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, October 05, 2013 16:33:40 Sean Kelly wrote:
 On Oct 5, 2013, at 4:09 PM, Andrej Mitrovic <andrej.mitrovich gmail.com> 

 On 9/30/13, Adam D. Ruppe <destructionator gmail.com> wrote:
 Is there anything we can do to automatically clean up if the user
 hits ctrl+c on Linux?

What's interesting is I just ran into this SEH enum in druntime for win32 by chance: CONTROL_C_EXIT But there's no equivalent for linux.

You need to trap SIGINT. But then you're stuck in a signal handler and so can't do much to clean up.

Well, you could do something like set a flag for the various threads to watch and throw when it's set to true, but you'd probably have to design everything around that to do anything like that, so it's arguably not a particularly good solution except in cases where you absolutely need to make sure that stuff shuts down correctly, and if you really need that, you should probably take another approach (like save regularly), since you can never guarantee that your app is going to shut down properly anyway (e.g. the power goes out). - Jonathan M Davis
Oct 05 2013
prev sibling parent "Wyatt" <wyatt.epp gmail.com> writes:
On Thursday, 31 October 2013 at 22:20:23 UTC, Timon Gehr wrote:
 I'm not sure. Excerpt from the iTunes EULA:

 "You also agree that you will not use these products for any 
 purposes prohibited by United States law, including, without 
 limitation, the development, design, manufacture or production 
 of nuclear, missiles, or chemical or biological weapons."

 http://www.apple.com/legal/internet-services/itunes/appstore/dev/stdeula/

I would classify forcing someone to use iTunes as "psychological warfare". Unfortunately, that's not covered by the EULA. ;) -Wyatt
Nov 01 2013