Coding

POSIX File Handling and Undefined Behaviour

Whilst porting code between Linux and macOS I have come across two issues which make assumptions about how something works but in reality different implementations of libc handle them differently. In this post I’ll talk about recent issues I faced with fopen() and fclose() in codebases.

fopen()

In the code I was porting from Linux to macOS there was a section which opened a file in “a+” mode, read the contents and then as time went on appended more data to the file. Everything was going great, but in macOS the file wasn’t being read at all. The reason is undefined behaviour for the read pointer as outlined in the Linux man page for open:

POSIX is silent on what the
initial read position is when using this mode. For glibc, the
initial file position for reading is at the beginning of the
file, but for Android/BSD/MacOS, the initial file position for
reading is at the end of the file.

http://man7.org/linux/man-pages/man3/fopen.3.html

The Linux code was assuming that when the file was opened in “a+” mode the read pointer was always at the start of the file. But in macOS the read pointer is right at the end of the file when opened. Fixing this was as simple as a basic seek but it was difficult to find this behaviour difference documented outside of the Linux man pages.

fclose()

This issue comes from porting code the other way around, from macOS to Linux. The code in question did this:

fclose(fileptr);

Which is fine, but it was possible that this code could be executed when there is no file open and fileptr is NULL. In macOS this causes fclose() to just return with no operation executed. But in Linux fclose(NULL) will crash with a segmentation fault.

I couldn’t find any explicit documentation on this, but many instances of other people hitting this crash. POSIX doesn’t define what should happen if a NULL pointer is passed to fclose() so this becomes undefined behaviour. Again this was easy to fix with a simple ‘if’ statement.

The moral of the story

The key takeaway here is “undefined behaviour” may not always be explicitly defined in documentation. If there is no explicit documentation for a given input to or usage of a function it is likely that different operating systems will implement it in different ways.

LinuxJedi

Share
Published by
LinuxJedi
Tags: COpen Source

Recent Posts

Working with the AVR Dx family

In recent years, Microchip has launched a new range of AVR chips. They appear to…

4 days ago

My WordPress Slack ban

A couple of days ago, I got banned from the WordPress community Slack. As this…

5 days ago

Issues I found during WordPress.com to .org migration

Whilst migrating from wordpress.com to an installation of the open source WordPress, I hit some…

1 week ago

Why I moved my blog

Unfortunately, there is a war going on within the WordPress community. To stay as far…

1 week ago

Four new Amiga products for September 2024

Since the June Amiga Expo, I have been developing some new Amiga related products. I…

3 weeks ago

Repairing an Amiga that caught on fire!

Karl at Retro32 likes to challenge me, and this time he had an interesting one.…

1 month ago