Hacker News new | past | comments | ask | show | jobs | submit login

Yes. And there is code in the SQLite source tree (currently on a branch) that supports OFD locks. The problem we have is that SQLite is so widely deployed and is in so many systems and on so many platforms, that we have to continue to support Posix Advisory Locks (PAL) for the foreseeable future, for compatibility. It will be great if someday we can remove the PAL code. But for now, it has to stay in the tree.



Neat! Is there any reason it’s in a branch? OFD locks fully interoperate with regular POSIX locks, so there shouldn’t be any compatibility issue, except that SQLite would need to fall back on older kernels.


Since OFD locks are a GNUism, putting that code into the mainline would immediately break portability. I quite like my SQLite databases on illumos and ZFS, so if it couldn’t work on illumos because of a Linux-specific feature, that’d be a serious problem.


That's what #ifdef is for. SQLite has a number of those, given it runs even on platforms which are not POSIX at all!


I know what they are for and don’t need instruction on that, thank you very much.

I also know that #ifdefs are a bad practice with many pitfalls so their use should be kept to a minimum. There is a treatise on the subject written in the early ‘90’s that I now see is very much relevant, judging by your comment. I wish I could quote it but since I’m using a smartphone to type this it’s too much hassle to find it.

Regardless, from a software architecture’s point of view, introducing a GNUism or a Linuxism where it isn’t strictly necessary is an obviously bad idea.

How’d you fare with that GCC build on the mailing list from couple of years back, by the way?


Using #ifdefs to get more out of certain architectures or working around quirks of a platform is definitely not something I'd consider bad practice.

As long as it has a default way to fall back to that works everywhere, there is no harm in platform specific code guarded by #ifdefs or other but similar mechanisms provided by the language you use (golang has platform and OS detection!)


They are not a bad practice if their use is kept to a minimum, and if the #ifdef in question is picked out thoughtfully.

Dump the built-in preprocessor macros between two different compilers on the same OS and diff the output, it should become immediately clear what I mean. Now go to a different OS and do the same thing and you’ll see that the number of possible combinations of defines to pick explodes, and depending on the situation, the common subset might not even be useful for portability, as in not enough overlap.


Then what is the alternative where I don't loose good integration into OS capabilities while also being portable and not bloating the code?


Where POSIX or XPG6 are insufficient, use core functions from libc, having verified that they exist on all OS targets and that they behave the same, and build the required functionality on top of those.


But then you would not be able to, for example, take advantage of FreeBSD's pledge when available or SELinux to protect your application and the user.

Libc doesn't even remotely offer what some libraries want and it leaves out everything that OS can offer on top of POSIX and libc.

And what if I want to support Windows, Linux and BSD? Windows doesn't really have a libc and is definitely not even remotely compatible with POSIX.


Yes you wouldn't be able to take advantage of OS specific features, and you'd have to write platform agnostic code on top of what you do have, but that's the price to pay for portability.

Windows does have a libc, but unlike UNIX where it comes with the OS, on Windows it comes with Visual Studio. That's what the "Visual Studio redistributables" are, since Windows has no linker maps and therefore no ABI versioning. Also, Windows has had a POSIX subsystem since the Windows NT days. That's what Windows Services for UNIX ("Interix") runs on.

I'm not saying don't use #ifdefs at all; what I am saying is don't use any OS-specific features if you want your program to be portable, or at least don't use those OS specific features which would immediately preclude usage of your software on other operating systems.

The only exception to this rule is if you are specifically writing software optimized for an operating system, like for example AmigaOS, or illumos/Solaris, or FreeBSD. However, unlike GNU/Linux based operating systems, it is a practical affair to find enough common functionality in illumos/Solaris and the BSD's to write software optimized for all of those operating systems and still be portable between all of them. The same does not hold true for software which has been written using GNU features because they are completely proprietary to GNU and require porting to BSD's and illumos. Sometimes, it's not even feasible to port those features because they are misfeatures or so badly designed that they are broken out of the box.


>I'm not saying don't use #ifdefs at all; what I am saying is don't use any OS-specific features if you want your program to be portable, or at least don't use those OS specific features which would immediately preclude usage of your software on other operating systems.

But this is exactly what #ifdefs solve.

You both have a portable program and can rely on OS-specific features. You can #ifdef GNU behaviour so that you can use the GNU shit on Linux and rely on more portable behaviour if you don't have GNU. Or you use muslc which doesn't pull as much crap. You can #ifdef that too.

I think it seems you want contradictory things. On one hand you claim that portable programs are desirable, on the other you say that you shouldn't rely on OS specific behaviour.

All behaviour is OS specific and outside of very trivial programs I challenge you to find an application that does not rely on #ifdefs, OS specific behaviour or duplicating code while also being portable.

Portability is not what I'd consider the utmost goal of software engineering, that would be solving the problem. Then comes maintainability. Portability is something at the end of a fairly long list.


Portability is what made UNIX the most widespread and successful operating system of all time.

As an engineer yes I want to solve practical problems with a computer, but I also don’t want to dictate (within reason) which OS the user must use. For example, if one of potential users of my software has a really advanced FreeBSD or OpenBSD setup and they can compile link and package my software, it would enable them to keep the advantages of their setup, and my software would make their advanced setup even more useful, like compound return on investment. Another advantage of this approach is that by not dictating the platform, it makes the user more productive and saves their time. People just want to get a task done and solve a problem, and respecting their time should be one of the programmer’s priorities.


We're not dictating what the user is using for their OS, again as I mentioned, there should always be a pure POSIX fallback. But #ifdefs help to take advantage of what the OS can do if the user decides to do it and we should not take that away from the user either.

Additionally I feel like it should be mentioned that even when POSIX and UNIX was a thing, programs had to include #ifdefs because target platforms wouldn't support X or didn't support Y in the same way as another platform. POSIX may have been designed to help against that but people still had to port their software a lot, with lots of #ifdefs and runtime shims.


* Henry Spencer and Geoff Collyer (1992). "#ifdef Considered Harmful, or Portability Experience With C News". USENIX ’92 Proceedings. pp 185-197. https://usenix.org/legacy/publications/library/proceedings/s...


Yes, that’s the document! Thanks so much for locating it, really appreciate it!


Best practices in portability have evolved since the 90s. I understand that portable C from that time was a nightmare, but things have changed a lot.

As long as you have a well defined portability layer, it doesn't really matter if it uses #ifdef or separate files (actually SQLite can be embedded as a single file, so it matters, but still). The important point of Spencer's paper was that portability shouldn't be a second thought. In fact it also mentions how to use #ifdef, not just when not to use it.


Ah, darn, I'm a few hours late so you will probably miss it but I wanted to ask for a long time:

Sounds like a lot of stuff like this has accumulated. Your dedication to backwards compatibility (and testing) is always very impressive, but don't you ever get the urge to do a parallel "SQLite Next" effort as it were? Kind of like python had the 2/3 years.


I read somewhere that the developers of SQLite have a multi-decade support agreement with some big companies. If true, they will probably keep all the accumulated stuff. Any changes would only be additions and never break backwards compatibility.


There was an attempt to re-architect sqlite. Try searching for sqlite4.


Here is a discussion about how the sqlite4 experiment ended, from 8 months ago

https://news.ycombinator.com/item?id=15648280 (157 comments)

And the relevant commit (timestamp 2017-10-27):

https://sqlite.org/src4/artifact/56683d66cbd41c2e

> All development work on SQLite4 has ended. The experiment has concluded.

> Lessons learned from SQLite4 have been folded into SQLite3 which continues to be actively maintained and developed. This repository exists as an historical record. There are no plans at this time to resume development of SQLite4.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: