Fpc Access Violation if AppConfigDir doesn't exist.

classic Classic list List threaded Threaded
83 messages Options
12345
Reply | Threaded
Open this post in threaded view
|

Fpc Access Violation if AppConfigDir doesn't exist.

Giuliano Colla

Launching a Lazarus application in a freshly installed Linux system, I
found a condition which may be quite confusing for a normal user: the
main form was shown, the program didn't work, and there was no way to
close the form, which could only be closed by a killall from command line.

Launching from command line one could only see a
TApplication.HandleException Access Violation, which isn't much telling
for a normal user either.

It turned out that the reason was simply that the default AppConfigDir
(~/.config/ ) wasn't there, and therefore in the two usual lines

AppConfigFileName:= GetAppConfigFile(False);
ini := TIniFile.Create(AppConfigFileName);

the second line was generating the access violation.

Desktop specs tell where configuration data should go, but they don't
guarantee that the directory exists. Other applications take care of
creating if it doesn't exist, but its presence depends on which
applications you launch.

Of course, once one knows, one can use ForceDirectories in the
application code, but it would be much more user friendly if
XdgConfigHome (or SysConfigDir when it will be implemented) in sysutils
took care of that. You ask for the default configuration path to put
your data in, and you get a sane and *existing* path.
It would also be nice if TIniFile.Create didn't generate an Access
Violation if the file can't be created.

Should I open an issue on the bugtracker on this subject, or I'm the
only one to think that it's a bug/required feature?

Giuliano




_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Reinier Olislagers
On 9-2-2013 1:49, Giuliano Colla wrote:

> It turned out that the reason was simply that the default AppConfigDir
> (~/.config/ ) wasn't there, and therefore in the two usual lines
>
> AppConfigFileName:= GetAppConfigFile(False);
> ini := TIniFile.Create(AppConfigFileName);
>
> the second line was generating the access violation.
>
> Desktop specs tell where configuration data should go, but they don't
> guarantee that the directory exists. Other applications take care of
> creating if it doesn't exist, but its presence depends on which
> applications you launch.
>
> Of course, once one knows, one can use ForceDirectories in the
> application code, but it would be much more user friendly if
> XdgConfigHome (or SysConfigDir when it will be implemented) in sysutils
> took care of that. You ask for the default configuration path to put
> your data in, and you get a sane and *existing* path.
> It would also be nice if TIniFile.Create didn't generate an Access
> Violation if the file can't be created.
>
> Should I open an issue on the bugtracker on this subject, or I'm the
> only one to think that it's a bug/required feature?
>
If I were you, I'd open an issue. I agree this is a problem.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Michael Van Canneyt


On Sat, 9 Feb 2013, Reinier Olislagers wrote:

> On 9-2-2013 1:49, Giuliano Colla wrote:
>> It turned out that the reason was simply that the default AppConfigDir
>> (~/.config/ ) wasn't there, and therefore in the two usual lines
>>
>> AppConfigFileName:= GetAppConfigFile(False);
>> ini := TIniFile.Create(AppConfigFileName);
>>
>> the second line was generating the access violation.
>>
>> Desktop specs tell where configuration data should go, but they don't
>> guarantee that the directory exists. Other applications take care of
>> creating if it doesn't exist, but its presence depends on which
>> applications you launch.
>>
>> Of course, once one knows, one can use ForceDirectories in the
>> application code, but it would be much more user friendly if
>> XdgConfigHome (or SysConfigDir when it will be implemented) in sysutils
>> took care of that. You ask for the default configuration path to put
>> your data in, and you get a sane and *existing* path.
>> It would also be nice if TIniFile.Create didn't generate an Access
>> Violation if the file can't be created.
>>
>> Should I open an issue on the bugtracker on this subject, or I'm the
>> only one to think that it's a bug/required feature?
>>
> If I were you, I'd open an issue. I agree this is a problem.

It is not a problem.

You should READ the documentation when using functions:

http://www.freepascal.org/docs-html/rtl/sysutils/getappconfigdir.html

Specifically

"This does not mean that the directory exists, or that the user can write in this directory (especially if Global=True).
   It just returns the name of the appropriate location."

So it is not a bug.

We can maybe have an appropriate 'AllowCreate' or 'EnsureDir' parameter or so.
But for system config directories, this is nonsense, so it should be optional.

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Reinier Olislagers
On 9-2-2013 10:25, Michael Van Canneyt wrote:

> On Sat, 9 Feb 2013, Reinier Olislagers wrote:
>> On 9-2-2013 1:49, Giuliano Colla wrote:
>>> It turned out that the reason was simply that the default AppConfigDir
>>> (~/.config/ ) wasn't there, and therefore in the two usual lines
>>>
>>> AppConfigFileName:= GetAppConfigFile(False);
>>> ini := TIniFile.Create(AppConfigFileName);
>>>
>>> the second line was generating the access violation.
>>>
>>> Desktop specs tell where configuration data should go, but they don't
>>> guarantee that the directory exists. Other applications take care of
>>> creating if it doesn't exist, but its presence depends on which
>>> applications you launch.
>>>
>>> Of course, once one knows, one can use ForceDirectories in the
>>> application code, but it would be much more user friendly if
>>> XdgConfigHome (or SysConfigDir when it will be implemented) in sysutils
>>> took care of that. You ask for the default configuration path to put
>>> your data in, and you get a sane and *existing* path.
>>> It would also be nice if TIniFile.Create didn't generate an Access
>>> Violation if the file can't be created.
>>>
>>> Should I open an issue on the bugtracker on this subject, or I'm the
>>> only one to think that it's a bug/required feature?
>>>
>> If I were you, I'd open an issue. I agree this is a problem.
>
> It is not a problem.

It is indeed not a problem if this is user code, not default code in a
Lazarus application. Didn't understand Giuliano's message to mean that.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Giuliano Colla
In reply to this post by Michael Van Canneyt
Il 09/02/2013 10:25, Michael Van Canneyt ha scritto:

>
>
> On Sat, 9 Feb 2013, Reinier Olislagers wrote:
>
>> On 9-2-2013 1:49, Giuliano Colla wrote:
>>> It turned out that the reason was simply that the default AppConfigDir
>>> (~/.config/ ) wasn't there, and therefore in the two usual lines
>>>
>>> AppConfigFileName:= GetAppConfigFile(False);
>>> ini := TIniFile.Create(AppConfigFileName);
>>>
>>> the second line was generating the access violation.
>>>
>>> Desktop specs tell where configuration data should go, but they don't
>>> guarantee that the directory exists. Other applications take care of
>>> creating if it doesn't exist, but its presence depends on which
>>> applications you launch.
>>>
>>> Of course, once one knows, one can use ForceDirectories in the
>>> application code, but it would be much more user friendly if
>>> XdgConfigHome (or SysConfigDir when it will be implemented) in sysutils
>>> took care of that. You ask for the default configuration path to put
>>> your data in, and you get a sane and *existing* path.
>>> It would also be nice if TIniFile.Create didn't generate an Access
>>> Violation if the file can't be created.
>>>
>>> Should I open an issue on the bugtracker on this subject, or I'm the
>>> only one to think that it's a bug/required feature?
>>>
>> If I were you, I'd open an issue. I agree this is a problem.
>
> It is not a problem.
>
> You should READ the documentation when using functions:
>
> http://www.freepascal.org/docs-html/rtl/sysutils/getappconfigdir.html
>
> Specifically
>
> "This does not mean that the directory exists, or that the user can
> write in this directory (especially if Global=True).
>   It just returns the name of the appropriate location."
>
> So it is not a bug.
>
> We can maybe have an appropriate 'AllowCreate' or 'EnsureDir'
> parameter or so. But for system config directories, this is nonsense,
> so it should be optional.
>

I can easily accept that it's not a bug, but you must agree with me that
it's a problem.

If every user application must include code between GetAppConfigxx and
TIniFile.Create to extract the path and ensure that it exists, even for
the trivial case Global=false, then it's reasonable that the right place
for that code is in system functions, and not in user application.

Maybe the right thing to fix isn't GetAppConfigxx, but TInifile.Create,
which doesn't return any warning if the file path doesn't exist, and
will just SigSev on a subsequent ini.WriteWhatever.

TIniFile silently creates the file if it doesn't exist, letting you
think that it takes care of everything, then why shouldn't it also
create the path if it doesn't exist? (provided it's writable, of course,
but Global=true requires special handling in any case, it's not for
everybody).

Giuliano

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Michael Van Canneyt


On Sat, 9 Feb 2013, Giuliano Colla wrote:

> Il 09/02/2013 10:25, Michael Van Canneyt ha scritto:
>>
>>
>> On Sat, 9 Feb 2013, Reinier Olislagers wrote:
>>
>>> On 9-2-2013 1:49, Giuliano Colla wrote:
>>>> It turned out that the reason was simply that the default AppConfigDir
>>>> (~/.config/ ) wasn't there, and therefore in the two usual lines
>>>>
>>>> AppConfigFileName:= GetAppConfigFile(False);
>>>> ini := TIniFile.Create(AppConfigFileName);
>>>>
>>>> the second line was generating the access violation.
>>>>
>>>> Desktop specs tell where configuration data should go, but they don't
>>>> guarantee that the directory exists. Other applications take care of
>>>> creating if it doesn't exist, but its presence depends on which
>>>> applications you launch.
>>>>
>>>> Of course, once one knows, one can use ForceDirectories in the
>>>> application code, but it would be much more user friendly if
>>>> XdgConfigHome (or SysConfigDir when it will be implemented) in sysutils
>>>> took care of that. You ask for the default configuration path to put
>>>> your data in, and you get a sane and *existing* path.
>>>> It would also be nice if TIniFile.Create didn't generate an Access
>>>> Violation if the file can't be created.
>>>>
>>>> Should I open an issue on the bugtracker on this subject, or I'm the
>>>> only one to think that it's a bug/required feature?
>>>>
>>> If I were you, I'd open an issue. I agree this is a problem.
>>
>> It is not a problem.
>>
>> You should READ the documentation when using functions:
>>
>> http://www.freepascal.org/docs-html/rtl/sysutils/getappconfigdir.html
>>
>> Specifically
>>
>> "This does not mean that the directory exists, or that the user can write
>> in this directory (especially if Global=True).
>>   It just returns the name of the appropriate location."
>>
>> So it is not a bug.
>>
>> We can maybe have an appropriate 'AllowCreate' or 'EnsureDir' parameter or
>> so. But for system config directories, this is nonsense, so it should be
>> optional.
>>
>
> I can easily accept that it's not a bug, but you must agree with me that it's
> a problem.
>
> If every user application must include code between GetAppConfigxx and
> TIniFile.Create to extract the path and ensure that it exists, even for the
> trivial case Global=false, then it's reasonable that the right place for that
> code is in system functions, and not in user application.

Yes.
Like I said, we can imagine a parameter 'AllowCreate' or 'ForceCreate'.

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Bart-48
On 2/9/13, Michael Van Canneyt <[hidden email]> wrote:

> Like I said, we can imagine a parameter 'AllowCreate' or 'ForceCreate'.

GetAppConfigDir(Global : Boolean: ForceCreate: Booelan = false) : String;

While this can easily be implemented without breaking existing code,
this still does not solve the original problem.
If creating the directory fails, the function does not return an
errorcode, unless we decide to let it raise an exception in this
case..

Common programming sense would be to query the desired location, and
if it does not exists, try and create it,(for this the ForeceCreate
parameter is usefull) __and check__ if this went OK.

So, no matter how we change the GetAppConfigDir() function, it will
always require code for checking if all went OK.

Bart
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Michael Van Canneyt


On Sat, 9 Feb 2013, Bart wrote:

> On 2/9/13, Michael Van Canneyt <[hidden email]> wrote:
>
>> Like I said, we can imagine a parameter 'AllowCreate' or 'ForceCreate'.
>
> GetAppConfigDir(Global : Boolean: ForceCreate: Booelan = false) : String;
>
> While this can easily be implemented without breaking existing code,
> this still does not solve the original problem.
> If creating the directory fails, the function does not return an
> errorcode, unless we decide to let it raise an exception in this
> case..

Which is why I said 'we can imagine':
I didn't investigate all angles yet...

>
> Common programming sense would be to query the desired location, and
> if it does not exists, try and create it,(for this the ForeceCreate
> parameter is usefull) __and check__ if this went OK.
>
> So, no matter how we change the GetAppConfigDir() function, it will
> always require code for checking if all went OK.

There is only one way:
if the ForceCreate is implemented and if creation fails, an exception
will be raised.

In which case the
TIniFile.Create(...)
and so forth will not be executed, and probably many other things will
go wrong as well....

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Bart-48
On 2/9/13, Michael Van Canneyt <[hidden email]> wrote:

>> If creating the directory fails, the function does not return an
>> errorcode, unless we decide to let it raise an exception in this
>> case..
>

> There is only one way:
> if the ForceCreate is implemented and if creation fails, an exception
> will be raised.

And in this case the OP still needs to do an extra check
(try..except), so basically this does not solve his "problem" because
it is unsolvable without the programmer checking/validating what
GetAppConfigDir did.

function GetAppConfigDir(Global: Boolean; ForceCreate: Boolean;
WhatToDoIfCreationFails: TProcedure) would "solve" the original
problem ;-)

Bart

Bart
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Michael Van Canneyt


On Sat, 9 Feb 2013, Bart wrote:

> On 2/9/13, Michael Van Canneyt <[hidden email]> wrote:
>
>>> If creating the directory fails, the function does not return an
>>> errorcode, unless we decide to let it raise an exception in this
>>> case..
>>
>
>> There is only one way:
>> if the ForceCreate is implemented and if creation fails, an exception
>> will be raised.
>
> And in this case the OP still needs to do an extra check
> (try..except), so basically this does not solve his "problem" because
> it is unsolvable without the programmer checking/validating what
> GetAppConfigDir did.

Which is why I always write the code to check/create the dir myself.

But having the check/create in a central place can have its advantages.

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Giuliano Colla
On 02/09/2013 04:19 PM, Michael Van Canneyt wrote:

>
>
> On Sat, 9 Feb 2013, Bart wrote:
>
>> And in this case the OP still needs to do an extra check
>> (try..except), so basically this does not solve his "problem" because
>> it is unsolvable without the programmer checking/validating what
>> GetAppConfigDir did.
>
> Which is why I always write the code to check/create the dir myself.
>
> But having the check/create in a central place can have its advantages.
>

The advantages I can see that it would make easier using VendorName,
and, most of all,
that once it's been written and debugged it's written and debugged for
all users, while application code must be written and debugged each time!

Giuliano

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Graeme Geldenhuys-3
In reply to this post by Bart-48
On 2013-02-09 13:56, Bart wrote:
>
> While this can easily be implemented without breaking existing code,
> this still does not solve the original problem.
> If creating the directory fails, the function does not return an
> errorcode, unless we decide to let it raise an exception in this
> case..

That's why I think they should stay as two separate prodecures.

Regards,
  - Graeme -

--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Giuliano Colla
On 02/10/2013 12:43 PM, Graeme Geldenhuys wrote:
> On 2013-02-09 13:56, Bart wrote:
>> While this can easily be implemented without breaking existing code,
>> this still does not solve the original problem.
>> If creating the directory fails, the function does not return an
>> errorcode, unless we decide to let it raise an exception in this
>> case..
> That's why I think they should stay as two separate prodecures.
Looking more carefully into the matter, the real inconsistency is not in
GetAppConfigFile, or in GetAppConfigDir, which just do what they're
meant for, but in TIniFile:

1) When you use it to *read* configuration parameters, if the file
doesn't exist it silently just passes you the default values. This is
normal, because the first time the program runs it didn't yet have the
chance to write configuration data.

2) When you use it to *write* configuration parameters, it silently
creates the file, and puts there the parameters. This again is normal,
because the first time the program run the configuration file isn't
there yet.

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 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.

This was perhaps tolerable when GetAppPathConfigXx did not exist, and it
was developer responsibility to provide a reasonable path, taking into
account different target system, but today I'd expect TIniFile to take
care also of forcing the appropriate path, and to raise an exception if
it fails.

Giuliano

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Mattias Gaertner
On Mon, 11 Feb 2013 00:13:00 +0100
Giuliano Colla <[hidden email]> 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.

I get an exception in this case:
  inifile:=TIniFile.Create('/does/not/exist/bla.ini');
  inifile.WriteString('Sec','First','1');
  inifile.UpdateFile;

 
> 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.

Even if the directory exists the write may fail. So you must use a
try..except anyway.

 
> This was perhaps tolerable when GetAppPathConfigXx did not exist, and it
> was developer responsibility to provide a reasonable path, taking into
> account different target system, but today I'd expect TIniFile to take
> care also of forcing the appropriate path, and to raise an exception if
> it fails.


Mattias
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Michael Van Canneyt
In reply to this post by Giuliano Colla


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

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.

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Giuliano Colla
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  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Michael Van Canneyt


On Mon, 11 Feb 2013, Giuliano Colla wrote:

> 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.

That is not the problem of TIniFile, but of the application programmer.

TIniFile properly reports any error, as it should, with an exception.
It is always up to the application programmer to deal with such cases.

That this is sometimes tricky in a GUI application, cannot be helped.

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Mark Morgan Lloyd-5
In reply to this post by Giuliano Colla
Giuliano Colla wrote:

> 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.

I'd suggest that there are two separate cases here. In the first case,
near the start of a program you decide whether there is a preexisting
.ini file, create it if not, and if necessary update it to contain e.g.
the default name of a backend server. In the second case, at the the end
of a program run you save the current session's state.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Giuliano Colla
Il 11/02/2013 12:40, Mark Morgan Lloyd ha scritto:

> Giuliano Colla wrote:
>
>> 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.
>
> I'd suggest that there are two separate cases here. In the first case,
> near the start of a program you decide whether there is a preexisting
> .ini file, create it if not, and if necessary update it to contain
> e.g. the default name of a backend server. In the second case, at the
> the end of a program run you save the current session's state.
>
I was speaking of the second case(saving configuration data to your .ini
file).
When attempting to load configuration data, a try..finally is ok. If no
configuration data are available you already have a built-in mechanism
to provide default values.
But when attempting to save the current session's state at the end of
the program, a try..finally will mask any error, and possibly lead to an
unpleasant lock up.

Giuliano

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Fpc Access Violation if AppConfigDir doesn't exist.

Giuliano Colla
In reply to this post by Michael Van Canneyt
Il 11/02/2013 12:35, Michael Van Canneyt ha scritto:

>
>
> On Mon, 11 Feb 2013, Giuliano Colla wrote:
>
>> 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.
>
> That is not the problem of TIniFile, but of the application programmer.
>
> TIniFile properly reports any error, as it should, with an exception.
> It is always up to the application programmer to deal with such cases.
>
> That this is sometimes tricky in a GUI application, cannot be helped.
>

It can be helped both by reducing the likelihood of the event, as you've
done, and by not suggesting to use in that case a try..finally construct
in a GUI application, which would mask the errors.
This suggestion comes historically from Delphi literature, but
fpc/Lazarus developers should never forget that they're smarter than
Delphi people. ;-)

Giuliano

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
12345