Losing .prefs file after exception

14 views
Skip to first unread message

pvr...@btinternet.com

unread,
May 13, 2024, 9:17:36 AMMay 13
to fltk.general
Sometimes, if my app raises an exception while it is closing down, the .prefs file gets deleted. I've not got the bottom as the the original point of failure yet as it seems to happen when I have been communicating with other apps using both UDP and TCP sockets. My application's data is undamaged but I only notice the issue when I restart and have lost all my settings.

Is it possible to save a copy before overwriting with updates? Or alternatively provide an API to get the filename so I can make my own copy?

Regards Phil.

Philip Rose

unread,
May 13, 2024, 9:31:40 AMMay 13
to 'pvr...@btinternet.com' via fltk.general


On 13/05/2024 14:17, 'pvr...@btinternet.com' via fltk.general wrote:
Sometimes, if my app raises an exception while it is closing down, the .prefs file gets deleted. I've not got the bottom as the the original point of failure yet as it seems to happen when I have been communicating with other apps using both UDP and TCP sockets. My application's data is undamaged but I only notice the issue when I restart and have lost all my settings.

Is it possible to save a copy before overwriting with updates? Or alternatively provide an API to get the filename so I can make my own copy?

I know RTFM, I found Fl_Preferences::filename() - I'll look into this.


Regards Phil.


Phil.

--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/24589af1-8f78-4a7a-9e87-35d2bdc474f9n%40googlegroups.com.

Philip Rose

unread,
May 13, 2024, 11:24:11 AMMay 13
to 'Philip Rose' via fltk.general

On 13/05/2024 14:31, 'Philip Rose' via fltk.general wrote:
>
>
> On 13/05/2024 14:17, 'pvr...@btinternet.com' via fltk.general wrote:
>> Sometimes, if my app raises an exception while it is closing down,
>> the .prefs file gets deleted. I've not got the bottom as the the
>> original point of failure yet as it seems to happen when I have been
>> communicating with other apps using both UDP and TCP sockets. My
>> application's data is undamaged but I only notice the issue when I
>> restart and have lost all my settings.
>>
>> Is it possible to save a copy before overwriting with updates? Or
>> alternatively provide an API to get the filename so I can make my own
>> copy?
>
> I know RTFM, I found Fl_Preferences::filename() - I'll look into this.
>
I was able to do this and back the file up at the start of my app. I was
also able to check if the .prefs file looked corrupt (either didn't
exist or was zero length) and query the user if this was OK or whether
to kill the app.


This is a sticking plaster solution, as I don't think FLTK should be
able to delete the Preferences data in the first place.

>>
>> Regards Phil.
>
>
> Phil.
>
Phil.

imm

unread,
May 13, 2024, 11:30:18 AMMay 13
to fltkg...@googlegroups.com
On Mon, 13 May 2024 at 16:24, 'Philip Rose' wrote:
>
> I was able to do this and back the file up at the start of my app. I was
> also able to check if the .prefs file looked corrupt (either didn't
> exist or was zero length) and query the user if this was OK or whether
> to kill the app.
>
>
> This is a sticking plaster solution, as I don't think FLTK should be
> able to delete the Preferences data in the first place.

Phil,

Is it actually deleting the file? (I have not tried to test this...)
When I read your original report, I had imagined it was perhaps
re-writing the file, but with empty (or at least corrupted) data - I
hadn't imagined that the file was actually deleted.
That really does sound odd.

Beyond that, I have nothing useful...

Matthias Melcher

unread,
May 13, 2024, 11:50:59 AMMay 13
to fltk.general
I originally intended that Fl_Preferences is used as a local variable in a function. That way, the file is read, changed, and written back when the function exits. Reading a short prefs file from a solid state drive takes very little time.

I see that it is used as a global variable, even in our own example apps. It's not recommended, but if you must do that, you should call flush() whenever something important changes. This will write the preferences to disk, and avoids writing them when your app runs into an exception. If the exception is in a different thread, the prefs file may get corrupted.

Philip Rose

unread,
May 13, 2024, 12:08:43 PMMay 13
to 'Matthias Melcher' via fltk.general


On 13/05/2024 16:50, 'Matthias Melcher' via fltk.general wrote:
I originally intended that Fl_Preferences is used as a local variable in a function. That way, the file is read, changed, and written back when the function exits. Reading a short prefs file from a solid state drive takes very little time.

I see that it is used as a global variable, even in our own example apps. It's not recommended, but if you must do that, you should call flush() whenever something important changes. This will write the preferences to disk, and avoids writing them when your app runs into an exception. If the exception is in a different thread, the prefs file may get corrupted.


Thanks Matthias.

I might add a call to flush() when I update preferences. However the documentation does contain this statement:

Typically a preferences database is read at startup, and then reopened and written at app shutdown: 

Which sort of implies that the typical usage is a global variable created at start-up and deleted at shutdown.

I am trying to provoke the error now. Can I assume that the file is not re-written if no preferences have changed: that I need to provoke a change to get the rewrite to occur and trigger the problem.

--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.

Philip Rose

unread,
May 15, 2024, 9:25:06 AMMay 15
to 'Philip Rose' via fltk.general


On 13/05/2024 17:08, 'Philip Rose' via fltk.general wrote:


On 13/05/2024 16:50, 'Matthias Melcher' via fltk.general wrote:
I originally intended that Fl_Preferences is used as a local variable in a function. That way, the file is read, changed, and written back when the function exits. Reading a short prefs file from a solid state drive takes very little time.

I see that it is used as a global variable, even in our own example apps. It's not recommended, but if you must do that, you should call flush() whenever something important changes. This will write the preferences to disk, and avoids writing them when your app runs into an exception. If the exception is in a different thread, the prefs file may get corrupted.


Thanks Matthias.

I might add a call to flush() when I update preferences. However the documentation does contain this statement:

Typically a preferences database is read at startup, and then reopened and written at app shutdown: 

Which sort of implies that the typical usage is a global variable created at start-up and deleted at shutdown.

I am trying to provoke the error now. Can I assume that the file is not re-written if no preferences have changed: that I need to provoke a change to get the rewrite to occur and trigger the problem.


I take this back, I should have noticed the colon at the end of the quote and seen the example code.

So I have added a flush() whenever I update a preference data item (or group of them). That was a less drastic mod than removing the global Fl_Preferences item.

I have been unable to provoke the error. It may still occur as I suspect the exception is in the inter-process communication which typically runs in separate threads. But I am less likely to be doing IPC while I am doing something that changes the preferences, whereas I was more likely to have a conflict relying on the destructor to flush the file. 

I had a look at the destructor code for Fl_Preferences. I saw that the Fl_Preferences destructor only rewrites the file if the preferences are dirty.

Phil.

Greg Ercolano

unread,
May 15, 2024, 11:37:25 AMMay 15
to fltkg...@googlegroups.com


On 5/13/24 08:50, 'Matthias Melcher' via fltk.general wrote:
I originally intended that Fl_Preferences is used as a local variable in a function. That way, the file is read, changed, and written back when the function exits. Reading a short prefs file from a solid state drive takes very little time.

I see that it is used as a global variable, even in our own example apps. It's not recommended, but if you must do that, you should call flush() whenever something important changes.


    I'm not sure if it applies here, but I find it useful when writing files like preferences, and indeed all files of importance where a corruption from a partial write must be avoided, is to open/write to a temp file first, then rename() the file into its final position. The rename() is atomic, ensuring that when the old file is overwritten, the new file is in a complete state.

    This way if a write operation is interrupted somehow (by a crash, or the user killing it, network interruption, etc), the file is never corrupted.


Matthias Melcher

unread,
May 18, 2024, 8:12:37 AMMay 18
to fltk.general
pvr...@btinternet.com schrieb am Mittwoch, 15. Mai 2024 um 15:25:06 UTC+2:

I might add a call to flush() when I update preferences. However the documentation does contain this statement:

Typically a preferences database is read at startup, and then reopened and written at app shutdown:

Which sort of implies that the typical usage is a global variable created at start-up and deleted at shutdown.

I am trying to provoke the error now. Can I assume that the file is not re-written if no preferences have changed: that I need to provoke a change to get the rewrite to occur and trigger the problem.


I take this back, I should have noticed the colon at the end of the quote and seen the example code.

So I have added a flush() whenever I update a preference data item (or group of them). That was a less drastic mod than removing the global Fl_Preferences item.

That surely is bad wording on my side. I will rephrase that and also see if there is a way to make the use as a global variable safer, as it seems to have become the go-to solution. I will also do the renaming dance for the final file to avoid partial preferences files to be generated. I should find the time next week.

 - Matthias 
Reply all
Reply to author
Forward
0 new messages