Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2012-10

Why opening a file for write fails in fpc 2.6?

22 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Giuliano Colla

In Linux environment the following code:

   try
     USBOut := FileOpen(UsbDev,fmOpenWrite);
   except
     result := True;
   end;

is used in a Lazarus application to get a handle to write to an USB device, and did work fine in fpc 2.4.

I migrated the application to Lazarus 1.0 wich uses fpc 2.6, and it stopped working. FileOpen returns -1, without rising an exception, which made me struggle to find out what was happening.

To make it work I had to change from FileOpen to FileCreate, but I fail to understand the rationale behind that.
The file does exist because it's a physical device (/dev/ttyACM0), its existence is checked before that code, and the call to FileOpen(UsbDev,fmOpenRead) just before the above lines works properly so I don't understand while it should be created, and not just opened.

Moreover I don't understand why the call returns a -1, meaning that the Open failed, without rising an exception.

Is there a good reason for this change from 2.4 to 2.6 or it's just a bug?

Giuliano Colla Before activating the tongue, make sure that the brain is connected (anonymous)
Jonas Maebe
to Giuliano Colla
Giuliano Colla wrote 14 lines
In Linux environment the following code: try USBOut := FileOpen(UsbDev,fmOpenWrite); except result := True; end; is used in a Lazarus application to get a handle to write to an USB device, and did work fine in fpc 2.4. I migrated the application to Lazarus 1.0 wich uses fpc 2.6, and it stopped working. FileOpen returns -1, without rising an exception, which made me struggle to find out what was happening.

FPC 2.6 added support for file locking on Unix platforms. You probably should use

   USBOut := FileOpen(UsbDev,fmOpenWrite or fmShareDenyNone);

Otherwise FileOpen will try to get an exclusive (write) lock on that device, which may well not be possible.

Moreover I don't understand why the call returns a -1, meaning that the Open failed, without rising an exception.

Does FileOpen raise an exception in Delphi when locking fails?

Jonas

Jonas Maebe
to Giuliano Colla
Giuliano Colla wrote 13 lines
Jonas Maebe ha scritto: > > > FPC 2.6 added support for file locking on Unix platforms. You > probably should use > > USBOut := FileOpen(UsbDev,fmOpenWrite or fmShareDenyNone); > > Otherwise FileOpen will try to get an exclusive (write) lock on > that device, which may well not be possible. > Understood, thank you. But shouldn't it be the other way around, i.e. one should explicitly request an exclusive lock?

No, that is how the behaviour of this function is defined. Looking at the documentation, is seems that file locking for Unix was already implemented in FPC 2.4.0 though, so maybe that won't be the problem after all.

Show quoted text 7 lines
>> Moreover I don't understand why the call returns a -1, meaning >> that the Open failed, without rising an exception. > > Does FileOpen raise an exception in Delphi when locking fails? > I have no idea,

It's always a good idea to look at the documentation first. At least the FPC documentation clearly states that it will return -1 on error: http://www.freepascal.org/docs-html/rtl/sysutils/fileopen.html

but if it doesn't it's a Delphi bug, I'd say. What are exceptions there for, if not for telling you that what you requested cannot be done?

There are multiple ways to indicate a failure. Exceptions are a very expensive way for doing so, and generally should only be used in cases that are truly exceptional and/or indicate a fatal error. In other cases, using a special return value is generally much more appropriate.

Jonas

Giuliano Colla
to Jonas Maebe

Il 31/10/2012 14:45, Jonas Maebe ha scritto:

Show quoted text 12 lines
On 31 Oct 2012, at 14:35, Giuliano Colla wrote: > > Understood, thank you. But shouldn't it be the other way around, i.e. > one should explicitly request an exclusive lock? No, that is how the behaviour of this function is defined. Looking at the documentation, is seems that file locking for Unix was already implemented in FPC 2.4.0 though, so maybe that won't be the problem after all.

Well, from the way Delphi File Mode are defined since the dawn of times, if you don't or fmWrite with anything, the default behavior is to open in fmShareCompat mode (=0), a legacy DOS mode tied to the long time dead FCB inherited from CP/1, which, to my knowledge, doesn't grant an exclusive lock, and which has no Unix equivalent. IMHO opinion it would be more reasonable to map this mode to a plain non-locking mode, in Unix environment.

Show quoted text 11 lines
> but if it doesn't it's a Delphi bug, I'd say. What are exceptions > there for, if not for telling you that what you requested cannot be > done? There are multiple ways to indicate a failure. Exceptions are a very expensive way for doing so, and generally should only be used in cases that are truly exceptional and/or indicate a fatal error. In other cases, using a special return value is generally much more appropriate.

My bad. I hadn't realized that low level file operation such as FileOpen and FileCreate do not raise an exception on failure. I seldom use them, and only in connection with physical devices, where I always take care to verify the existence before attempting to read or write. So I just relied on a useless try-except construct.
It's very unlikely that such a failure would permit a program to continue running, I'd call it a fatal error, so an exception would be welcome, but that's life...

Giuliano

Jonas Maebe
to Giuliano Colla: Il 31/10/2012 14:45, Jonas Maebe ha scritto: Well, from the way Delphi File Mode are…
Giuliano Colla wrote
Well, from the way Delphi File Mode are defined since the dawn of times, if you don't or fmWrite with anything, the default behavior is to open in fmShareCompat mode (=0), a legacy DOS mode tied to the long time dead FCB inherited from CP/1, which, to my knowledge, doesn't grant an exclusive lock, and which has no Unix equivalent. IMHO opinion it would be more reasonable to map this mode to a plain non-locking mode, in Unix environment.

I based the implementation on the Delphi for Windows behaviour, where it does result in taking an exclusive lock. It seems that on Linux (Kylix) they did map it to fmShareDenyNone though: https://groups.google.com/forum/?fromgroups=#!topic/borland.public.delphi.language.delphi.general/edJN6SobJP8

I'm personally not a big fan of having different behaviour across platforms when it can be avoided without too much trouble, and I doubt there's much source code around that relies on Kylix-specific behaviour. I don't know what XE2 does on Mac OS X.

Jonas

Tomas Hajny
to Giuliano Colla: Il 31/10/2012 14:45, Jonas Maebe ha scritto: Well, from the way Delphi File Mode are…
Giuliano Colla wrote
Il 31/10/2012 14:45, Jonas Maebe ha scritto: > On 31 Oct 2012, at 14:35, Giuliano Colla wrote:

.
.

Show quoted text 18 lines
>> but if it doesn't it's a Delphi bug, I'd say. What are exceptions >> there for, if not for telling you that what you requested cannot be >> done? > > There are multiple ways to indicate a failure. Exceptions are a very > expensive way for doing so, and generally should only be used in cases > that are truly exceptional and/or indicate a fatal error. In other > cases, using a special return value is generally much more appropriate. > > My bad. I hadn't realized that low level file operation such as FileOpen and FileCreate do not raise an exception on failure. I seldom use them, and only in connection with physical devices, where I always take care to verify the existence before attempting to read or write. So I just relied on a useless try-except construct. It's very unlikely that such a failure would permit a program to continue running, I'd call it a fatal error, so an exception would be welcome, but that's life...

I don't agree with your statement that such an error wouldn't allow the program to continue running. Vice versa, there are many situations where the result may be used for a different behaviour of the respective program. As an example, you may use the return value from FileCreate for checking whether the user supplied a valid file name in his input to the program (and ask for another file name afterwards), you may also check whether you can access the respective file in read/write mode (and thus allow user to change the file) or you need to stick to read-only mode (and thus allow just viewing/reading the content), etc.

Tomas

Giuliano Colla
to Tomas Hajny

Il 01/11/2012 09:28, Tomas Hajny ha scritto:

Show quoted text 32 lines
On Thu, November 1, 2012 00:24, Giuliano Colla wrote: > Il 31/10/2012 14:45, Jonas Maebe ha scritto: >> On 31 Oct 2012, at 14:35, Giuliano Colla wrote: . . >>> but if it doesn't it's a Delphi bug, I'd say. What are exceptions >>> there for, if not for telling you that what you requested cannot be >>> done? >> There are multiple ways to indicate a failure. Exceptions are a very >> expensive way for doing so, and generally should only be used in cases >> that are truly exceptional and/or indicate a fatal error. In other >> cases, using a special return value is generally much more appropriate. >> >> > My bad. I hadn't realized that low level file operation such as FileOpen > and FileCreate do not raise an exception on failure. I seldom use them, > and only in connection with physical devices, where I always take care > to verify the existence before attempting to read or write. So I just > relied on a useless try-except construct. > It's very unlikely that such a failure would permit a program to > continue running, I'd call it a fatal error, so an exception would be > welcome, but that's life... I don't agree with your statement that such an error wouldn't allow the program to continue running. Vice versa, there are many situations where the result may be used for a different behaviour of the respective program. As an example, you may use the return value from FileCreate for checking whether the user supplied a valid file name in his input to the program (and ask for another file name afterwards), you may also check whether you can access the respective file in read/write mode (and thus allow user to change the file) or you need to stick to read-only mode (and thus allow just viewing/reading the content), etc.

You may be right, but the try-except construct is there exactly to permit you to handle those situations.
However I'd like to point out a significant inconsistency. Please give a look to the following piece of code:

procedure TForm1.Button1Click(Sender: TObject);
var
   MyFile: TextFile;
   AName: String;
begin
   AName:= 'BadName.txt';
   AssignFile(MyFile,AName);
   Reset(MyFile);  <==== Raises an Exception: EInOutError File not found
end;
procedure TForm1.Button2Click(Sender: TObject);
var
   MyFile: Integer;
   AName: String;
begin
   AName:= 'BadName.txt';
   MyFile:= FileOpen(AName,fmOpenRead); <===== Just sets MyFile to -1
end;

Both procedures perform exactly the same action, i.e. they attempt to open for reading the non existing file BadName.txt. The first one gives rise to an exception. The second one doesn't. Your considerations should apply to both, or to none. As it is, it's rather inconsistent.

Just my 2c

Giuliano

Jonas Maebe
to Giuliano Colla
Giuliano Colla wrote 12 lines
You may be right, but the try-except construct is there exactly to permit you to handle those situations. However I'd like to point out a significant inconsistency. Please give a look to the following piece of code: procedure TForm1.Button1Click(Sender: TObject); var MyFile: TextFile; AName: String; begin AName:= 'BadName.txt'; AssignFile(MyFile,AName); Reset(MyFile); <==== Raises an Exception: EInOutError File not found end;

That depends on the state of the {$i+/-} directive.

Jonas

Giuliano Colla
to Jonas Maebe: I based the implementation on the Delphi for Windows behaviour, where it does result in…

Il 01/11/2012 01:07, Jonas Maebe ha scritto:

I'm personally not a big fan of having different behaviour across platforms when it can be avoided without too much trouble,

In general I agree with you. I often debate with Lazarus team because, in order to provide "native behavior" they make it difficult to achieve consistent look and behavior on different platforms (which is just what I'm usually required from my customers). But I end up getting the worst of both worlds: inconsistent behavior where I need consistency, consistent behavior where I'd happily do without :-(

and I doubt there's much source code around that relies on Kylix-specific behaviour.

I'm among the unhappy former Kylix users, trying to carry on with a lot of unsupported Kylix code :-(

Giuliano

Giuliano Colla
to Jonas Maebe: That depends on the state of the {$i+/-} directive. Jonas

Il 01/11/2012 11:43, Jonas Maebe ha scritto:

Show quoted text 16 lines
On 01 Nov 2012, at 11:40, Giuliano Colla wrote: > You may be right, but the try-except construct is there exactly to permit you to handle those situations. > However I'd like to point out a significant inconsistency. Please give a look to the following piece of code: > > procedure TForm1.Button1Click(Sender: TObject); > var > MyFile: TextFile; > AName: String; > begin > AName:= 'BadName.txt'; > AssignFile(MyFile,AName); > Reset(MyFile); <==== Raises an Exception: EInOutError File not found > end; That depends on the state of the {$i+/-} directive.

Which doesn't affect FileOpen behavior.

Giuliano

Jonas Maebe
to Giuliano Colla: Il 01/11/2012 01:07, Jonas Maebe ha scritto: In general I agree with you. I often debate…
Giuliano Colla wrote
Il 01/11/2012 01:07, Jonas Maebe ha scritto: > I'm personally not a big fan of having different behaviour across platforms when it can be avoided without too much trouble, In general I agree with you. I often debate with Lazarus team because, in order to provide "native behavior" they make it difficult to achieve consistent look and behavior on different platforms (which is just what I'm usually required from my customers).

In that case, using a framework that relies on a native widgetset is the wrong the approach. You would probably be happier with something like MSEGUI or fpGUI (well, apart from the fact that neither is VCL-compatible in any way). Trying to emulate Windows behaviour, or a mix of various platform-behaviours, on all platforms using native widget sets, now that would be a great example of the worst of all worlds.

Jonas

Jonas Maebe
to Giuliano Colla: Il 01/11/2012 11:43, Jonas Maebe ha scritto: Which doesn't affect FileOpen behavior.…
Giuliano Colla wrote 8 lines
Il 01/11/2012 11:43, Jonas Maebe ha scritto: > On 01 Nov 2012, at 11:40, Giuliano Colla wrote: > >> Reset(MyFile); <==== Raises an Exception: EInOutError File not found >> end; > That depends on the state of the {$i+/-} directive. > Which doesn't affect FileOpen behavior.

No, because {$i+/-} dates back to Turbo Pascal and is specifically tied to the "standard" I/O operations. The Delphi-ones only support result-based checking. It's a completely new API with its own convention.

Jonas

Giuliano Colla
to Jonas Maebe: In that case, using a framework that relies on a native widgetset is the wrong the…

Il 01/11/2012 11:56, Jonas Maebe ha scritto:

On 01 Nov 2012, at 11:50, Giuliano Colla wrote: > In general I agree with you. I often debate with Lazarus team because, in order to provide "native behavior" they make it difficult to achieve consistent look and behavior on different platforms (which is just what I'm usually required from my customers). In that case, using a framework that relies on a native widgetset is the wrong the approach. You would probably be happier with something like MSEGUI or fpGUI (well, apart from the fact that neither is VCL-compatible in any way).

Being stuck with a lot of Kylix code, I found it quite heavy a migration toward fpGUI (or MSEGUI). VCL and CLX are contiguous enough to allow a migration without too much hassle.
Luckily even if the Kylix development is not possible on modern platform, it's still possible with a few kludges to run Kylix applications. One only needs to keep alive legacy platforms for development.

Now I'm looking forward with interest to CustomDrawn, which should fit much better my needs, and I'm also trying to contribute, bounded by the limits of my available time (and capabilities).

Giuliano

Graeme Geldenhuys
to Giuliano Colla: Il 01/11/2012 11:56, Jonas Maebe ha scritto: Being stuck with a lot of Kylix code, I…
Giuliano Colla wrote
Being stuck with a lot of Kylix code, I found it quite heavy a migration toward fpGUI (or MSEGUI).

Our company has invested lots of time and money in developing CLX (Kylix) applications. We have ported quite a few of them to fpGUI, and it was not that The UI is easy to recreate
- The Kylix application code must be adapted no matter which GUI toolkit you use. Even so, most of the code can be reused as-is.

fpGUI is different to VCL or LCL by design - but the general UI concepts are very similar. Everybody I have spoken to have said that picking up fpGUI is rather easy because of a very clear design and API.

Kylix development is not possible on modern platform, it's still possible with a few kludges to run Kylix applications. One only needs to keep alive legacy platforms for development.

Correct. We simply run Kylix IDE in a Red Hat 9 VM for continued development and application maintenance, but the applications themselves run just fine even on the latest Linux distros like OpenSUSE 12.2 or Ubuntu 12.10 - simply ship your app with the required *.so files and set the LD_LIBRARY_PATH before launching your app.

We have Kylix apps that haven't been touched since 2003, and they still run on today's distros.

Now I'm looking forward with interest to CustomDrawn, which should

I've recently (about 3 weeks ago) is still
years away form being usable in production code. Simple things like the default Cut/Copy/Paste popup menu in text widgets don't exist. Tabbing in reverse order between widgets don't work etc. The more you look the more issues you will find in LCL-CustomDrawn. This doesn't mean LCL-CustomDrawn in bad, it just means it is not near being ready to be used in real world applications.

Regards,
- Graeme -

Mark Morgan Lloyd
to Graeme Geldenhuys: Which might not be a bad thing - depending on your project needs. VCL (and LCL) is too…
Graeme Geldenhuys wrote 8 lines
On 2012-11-01 10:56, Jonas Maebe wrote: > You would probably be happier with something > like MSEGUI or fpGUI (well, apart from the fact that neither is > VCL-compatible in any way). Which might not be a bad thing - depending on your project needs. VCL (and LCL) is too Windows centric, and has no place in Linux or Mac OS X platforms.

That is a matter of opinion, and other developers would argue the point. Over the years, Windows has gained a lot of things that were originally implemented by other OSes, as such it could be considered to be the "standard bearer" for workstation OSes. If that means that workstation UIs and widget sets are heavily influenced by Windows, that might be something best lived with.

However I (for one) am strongly in favour of having at least one widget set that will run on top of X or even a frame buffer, discarding questionable cruft that has been pulled in by recent implementations of GTK etc.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]
Graeme Geldenhuys
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote
That is a matter of opinion, and other developers would argue the point.

When I say "windows centric" I mean LCL imitating the WinAPI in LCL-GTK2, LCL-Qt and LCL-Carbon. Most of the times that just doesn't fit.

"standard bearer" for workstation OSes. If that means that workstation UIs and widget sets are heavily influenced by Windows, that might be something best lived with.

As for UI. We have found with our company testing that as long as the UI is similar (no need to be identical to native UI), that is good enough for end-users to be able to use your application. Windows users have no problem learning to use iOS or Android devices or the millions of Web Apps (gmail, outlook.com, etc) - yet the UI is completely different to their desktops.

Then you also get companies like Embarcadero[1] and projects like Qt[2] promoting the idea of custom looking UI to make your product stand out from the crowd. The ability to brand your application - a common marketing tactic.

[1] VCL styles in the XE range of products, and Firemonkey styles. [2] Qt5 will have a new style, Forge, which will look identical on all platforms.

However I (for one) am strongly in favour of having at least one widget set that will run on top of X or even a frame buffer, discarding

I have renewed interest in targeting the Linux Frame Buffer, and with the same design changes, open fpGUI's design up for other possible backends like OpenGL, SDL, Cairo, Haiku etc with much less effort. A new branch of this development will start shortly. That would hopefully mean fpGUI can target Android and Raspberry Pi development with better performance from the GPU.

Regards,
- Graeme -

Giuliano Colla
to Graeme Geldenhuys: Our company has invested lots of time and money in developing CLX (Kylix) applications.…

Il 01/11/2012 13:09, Graeme Geldenhuys ha scritto:

Show quoted text 10 lines
On 2012-11-01 11:49, Giuliano Colla wrote: Now I'm looking forward with interest to CustomDrawn, which should I've recently (about 3 weeks ago) is still years away form being usable in production code. Simple things like the default Cut/Copy/Paste popup menu in text widgets don't exist. Tabbing in reverse order between widgets don't work etc. The more you look the more issues you will find in LCL-CustomDrawn. This doesn't mean LCL-CustomDrawn in bad, it just means it is not near being ready to be used in real world applications.

I fully agree with you. CustomDrawn is at a very preliminary stage. I'm not even sure that the current implementation of LCL-CustomDrawn will ever lead to a usable thing. The approach is a brute force one: just one window for form, and redraw all the widgets on the full form each time something changes. Even cursor blinking is achieved by redrawing the full form. You can imagine how slow everything becomes when your window has a reasonable size, and is populated by a reasonable number of widgets.

That's the problem of many open source projects. They're mostly created by developers which think to their applications, and take care primarily of what they need. CustomDrawn was originated by Felipe, who's mainly interested in his Magnifying Glass project. Once he manages to make it work on his target platform, he's more or less finished.

But the same holds true for me. In my applications I don't use neither the Cut/Copy/Paste popup menu, nor tabbing (forward or reverse), so you may bet that if I contribute to CustomDrawn, be it the current implementation or a fully new one, those features will end up quite low in my ToDo list.

That's the main reason I look with more interest to LCL than fpGUI. Simply because LCL provides already implemented much more features I need with respect to fpGUI, (at least up to the last time I evaluated fpGUI).
When the time comes that I'm really forced to abandon Kylix, then I'll try to see if it's more work to implement what I need (and which won't certainly be there) on CustomDrawn (most likely stealing quite a lot from fpGUI), or to contribute to fpGUI, in order to get what I need. For the moment I've devoted the little time I have available to some contributions to CustomDrawn, because I have more confidence with LCL environment, and this makes things easier for me.

Giuliano

Graeme Geldenhuys
to Giuliano Colla
Giuliano Colla wrote
That's the main reason I look with more interest to LCL than fpGUI. Simply because LCL provides already implemented much more features I need with respect to fpGUI, (at least up to the last time I evaluated fpGUI).

That's probably been a while back. If you evaluate it again, and you do find things missing, please let me know. That would be much appreciated. You can contact me via email or via the fpgui.* newsgroups.

Regards,
- Graeme -

Giuliano Colla
to Graeme Geldenhuys

Graeme Geldenhuys ha scritto:

Show quoted text 10 lines
On 2012-11-01 23:32, Giuliano Colla wrote: > That's the main reason I look with more interest to LCL than fpGUI. > Simply because LCL provides already implemented much more features I > need with respect to fpGUI, (at least up to the last time I evaluated > fpGUI). That's probably been a while back. If you evaluate it again, and you do find things missing, please let me know. That would be much appreciated. You can contact me via email or via the fpgui.* newsgroups.

I promise (crossed fingers) that I'll do it as soon as I have some time available (not very soon, unfortunately). In principle I find fpGUI to be built on a much more stable ground than the quicksands of always changing widgetsets of Lazarus team.

Giuliano

Giuliano Colla Before activating the tongue, make sure that the brain is connected (anonymous)