[Linux] Try/Catch

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
IchMagBier
Posts: 49
Joined: Jan 13, 2018 8:47
Location: Germany
Contact:

[Linux] Try/Catch

Postby IchMagBier » Jan 04, 2020 8:56

Hello :)

I wrote this simple exception handler for Linux, which can catch segmentation faults and user defined exceptions, without terminating the program:

Code: Select all

#include "trycatch.bi"

try ' // segmentation fault
   dim as long ptr bla
   *bla = 42
catch(e as Exception)
   if e = SEGMENTATION_FAULT then
      print "Fix your pointer!"
   else
      print "Unknown exception: "+str(e)
   end if
endtry

try ' // illegal machine code
   asm ud2
catch(e as Exception)
   if e = ILLEGAL_INSTRUCTION then
      print "Fix your code!"
   else
      print "Unknown exception: "+str(e)
   end if
endtry

try ' // user defined exceptions
   throw(42)
catch(e as Exception)
   print "Unknown exception: "+str(e)
endtry


trycatch.bi:

Code: Select all

#include "crt/setjmp.bi"

#define ILLEGAL_INSTRUCTION 4
#define BUS_ERROR 7
#define SEGMENTATION_FAULT 11

type sigaction
   sa_sigaction as sub(signal as long) ' void (*sa_sigaction) (int, siginfo_t *, void *)
   as uinteger sa_mask(1024 / (8*8))
   as long sa_flags
   sa_restorer as sub()
end type

extern "C"
   declare sub sigaction(signal as long, __act as sigaction ptr, __oact as sigaction ptr)
end extern

dim shared as jmp_buf __signal_jmp_buf
dim shared as long __sa_signal, __fault

sub __sigsegv(signal as long)
   __sa_signal = signal
   longjmp(@__signal_jmp_buf, 1)
end sub

dim shared as sigaction __sa
for i as ulong = 0 to 1024/(8*8)
   __sa.sa_mask(i) = 0
next
__sa.sa_restorer = 0
__sa.sa_flags = 0
__sa.sa_sigaction = @__sigsegv()
sigaction(ILLEGAL_INSTRUCTION, @__sa, 0)
sigaction(BUS_ERROR, @__sa, 0)
sigaction(SEGMENTATION_FAULT, @__sa, 0)

#macro try
   __fault = setjmp(@__signal_jmp_buf)
   if __fault = 0 then
#endmacro

#macro catch(signal)
   else
      dim signal = __sa_signal
#endmacro

sub throw(signal as long)
   __sa_signal = signal
   longjmp(@__signal_jmp_buf, signal)
end sub

#define endtry end if
type Exception as long


This isn't limited to exceptions, you can catch other POSIX-signals aswell like this:

Code: Select all

try
catch(e as Exception)
   if e = 1 then ' SIGHUP
endtry
Xusinboy Bekchanov
Posts: 153
Joined: Jul 26, 2018 18:28

Re: [Linux] Try/Catch

Postby Xusinboy Bekchanov » Jan 04, 2020 10:44

Such things can be entered into keywords, thank you.
In my opinion, these keywords are already in vb.net.
Tourist Trap
Posts: 2815
Joined: Jun 02, 2015 16:24

Re: [Linux] Try/Catch

Postby Tourist Trap » Jan 04, 2020 11:10

Xusinboy Bekchanov wrote: these keywords are already in vb.net

Yes they are used all the time. Don't know if it's always good, but at least this prevents crashes.
If we could have the same also for windows that would be really a feature I think.
caseih
Posts: 1423
Joined: Feb 26, 2007 5:32

Re: [Linux] Try/Catch

Postby caseih » Jan 04, 2020 15:54

Be careful handling SIGSEGV. Usually a segfault is a sure sign of memory corruption and the only safe thing to do is to write out your memory state for future debugging and crash. Of course there are reasons for handling that signal, such as managing child processes.
Tourist Trap wrote:
Xusinboy Bekchanov wrote: these keywords are already in vb.net

Yes they are used all the time. Don't know if it's always good, but at least this prevents crashes.
If we could have the same also for windows that would be really a feature I think.
What do you mean by "prevent crashes?" Exception handling should not prevent crashes. As I said about segfaults, crashes are often the only sensible thing to do. A program cannot recover from memory corruption generally; rather the bug must be fixed in the source code that caused the memory corruption.

I think a good rule of thumb with exceptions is to not catch them. They are, after all, by definition exceptional events. Unless your program is expecting them and has explicitly been designed to mitigate them, you shouldn't catch them, but let them bubble up to another layer that is prepared to deal with them, or to crash out. Opening a file for reading that doesn't exist could cause an exception that a program can easily deal with. Other situations are more complex. I think this is why most programmers cringe at exception handling. That's why I like the way Python does exceptions. 99% of the time you don't worry about them and they work as designed.
Tourist Trap
Posts: 2815
Joined: Jun 02, 2015 16:24

Re: [Linux] Try/Catch

Postby Tourist Trap » Jan 08, 2020 6:10

caseih wrote:]What do you mean by "prevent crashes?" Exception handling should not prevent crashes. As I said about segfaults, crashes are often the only sensible thing to do.

I agree with all you say here, but my focus was on the TRY. We try, this goes wrong, so we make a step back and and finally do otherwise. My feeling however is that, 1) a programmer should not just try to execute things that he knows are prone to crash, but rather avoid them. And 2) I was never sure if we really can "step back".

The other point is that in .net, you are often expected to be selling your programs to any potential user. So you don't want it to crash in a hard way. This is what customers really hate.

All this said, again I think that we should use this with parcimony, and yet it would be a valuable feature in the case you are sharing your program with others that hate crashes, and for development purpose also, and so on.

I don't see how Python *specifically* handle the exception. I use it only in the interpreted environnement, so it doesn't compare to my eyes to when the executable is left walking alone.
caseih
Posts: 1423
Joined: Feb 26, 2007 5:32

Re: [Linux] Try/Catch

Postby caseih » Jan 08, 2020 19:54

I guess my point is that if something has gone so wrong that it's going to lead to a segfault (IE the program will blow up), then catching that is just hiding the problem and allowing it to become much worse and potentially lose a lot more of the user's data. I'm not talking about trying to read from a file that doesn't exist. I'm talking about the segfault here. In Unix operating systems you should very rarely handle SIGSEGV. I'm specifically talking about @IchMagBier's post. Catching segmentation faults is very bad usually, except to do emergency bail out. Ultimately after a segfault, the only appropriate course of action is to abort the program. Because all bets are off.

More generally for exception handling, any exception that you haven't explicitly planned for should be allowed to ultimately crash the program (hopefully gracefully) and generate a debug trace or whatever. That's honestly the only way you'll ever find and solve the problems that caused the exceptions. Yes I'm talking about commercial software here too. Silent failure is far worse than a user's bug report. Some commercial programs deal with crashing by logging the error and quickly restarting the crashed part. Probably a good strategy for making robust software.

You describe two possibilities with regards to error handling that are worth discussing. Put in another way, what you described can be summarized by the more common phrases in computer programming:
- look before you leap
- better to ask forgiveness than permission.

The first is very common, however there are circumstances where this can be a bad idea. For example, programmers sometimes check for the existence of a file before operating on it. This sounds logical, but in a multi-user, multi-core system, this can lead to failure. Files can disappear between the time you check for the file's existence, and the time the file operation is commenced. This is why often it's better to just blindly try the file operation and catch the common errors there (asking permission instead of forgiveness).
marcov
Posts: 2839
Joined: Jun 16, 2005 9:45
Location: Eindhoven, NL
Contact:

Re: [Linux] Try/Catch

Postby marcov » Jan 08, 2020 20:17

The trick of try catch and try finally is nested use. This is where macro based workarounds usually fail.
IchMagBier
Posts: 49
Joined: Jan 13, 2018 8:47
Location: Germany
Contact:

Re: [Linux] Try/Catch

Postby IchMagBier » Jan 10, 2020 20:09

caseih wrote:I'm specifically talking about @IchMagBier's post. Catching segmentation faults is very bad usually, except to do emergency bail out. Ultimately after a segfault, the only appropriate course of action is to abort the program. Because all bets are off.

Well, I was in need for a "try catch" for my program, where an in-memory compiler compiles and executes some user-written code and I didn't want the whole program to crash when a segfault occurs in there, but instead exit the function, log the error and jump back to the main program.

Handling segfaults may also be useful to crash more "gracefully". Like displaying a proper error-message, maybe graphically, instead of showing a simple "Segmentation fault" in the terminal. By inspecting the "rip"-value from where the crash occured, you could tell the user, what exactly went wrong and how he could fix it. Maybe some corrupted file caused the crash, or a shared memory buffer wasn't correctly initialized or whatever. You could also include some register dumps or values from the stack to show more useful debug info.

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 1 guest