Il 11/02/2013 09:21, Michael Van Canneyt ha scritto:


On Mon, 11 Feb 2013, Giuliano Colla wrote:

3) But if also the *path* to the file doesn't yet exist, it just crashes without rising an exception that the user application can handle somehow.

This is incorrect. It does tell you why it fails.


This is rather unpleasant, because the path provided by GetAppConfigXx does usually exist, so you have an application which 99% of the times works just fine, and 1% of the times crashes without telling why.

It tells you *exactly* why it 'crashes':

home: >./ti
An unhandled exception occurred at $000000000042AE87:
EFCreateError: Unable to create file "/tmp/path/to/nothing.txt"
  $000000000042AE87


This is true only if you invoke the program from command line, which is something the end user will never do. Consider that this sort of errors doesn't pop up when you're developing, but rather after you've deployed your application. Let's assume that saving configuration is on a FormClose procedure, as usual, and you have a try..finally construct, as usual.
Your user starts the program by clicking on a launching Icon.
When he clicks on a Close button, if the path doesn't exist the program won't be terminated, and he's left with a window he can't close. On a terminal you can see

TApplication.HandleException Unable to create file "/home/colla/.pippo/uclc.cfg"
  Stack trace:
  $080BAF29
[..]
exception at 080BAF29:
Unable to create file "/home/colla/.pippo/uclc.cfg".

But no error is shown on the screen (try..finally has trapped it), and the form is not closed. Then the user will attempt to click again on the close button of a form which is already "almost" closed. On a terminal you can see:

TApplication.HandleException Access violation
  Stack trace:
[..]
  $082A9B6D  GTK2WSBUTTON_CLICKED,  line 2417

But again nothing on the screen. The program hangs here. From command line you need a ^C to terminate. Otherwise you need a killall. Which isn't a very good situation for an end user.

home: >cat ti.pp
program ti;

uses inifiles;

begin
  with TMemIniFile.create('/tmp/path/to/nothing.txt') do
    try
      WriteString('A','B','C');
      UpdateFile;
    finally
      Free;
    end;
end.

However, I agree that it should try to create the path as well.
I have adapted the implementation.

You'll get an error telling you if it failed to create the dir:
An unhandled exception occurred at $0000000000427F7E:
EInOutError: Could not create directory "/my/path/to/"
  $0000000000427F7E

Which means that you are still (as previously) responsible for catching possible errors.
But these errors should be less frequent with this change.

Thank you, attempting to create the path is a welcome improvement. It makes TIniFile behavior much more consistent.

However, what I've learned from this episode is that while attempting to save configuration data using TINIFile on program termination you should never use a try..finally construct, as it's suggested everywhere, but rather a try..except (or both). Otherwise you'll never be able to catch possible errors.

Giuliano

_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to