Some C++/RTL questions

Post Reply

Topic author
mberryman
Active Contributor
Posts: 27
Joined: Sat Sep 02, 2023 1:31 pm
Reputation: 0
Location: Colorado Springs, CO, USA
Status: Offline

Some C++/RTL questions

Post by mberryman » Wed Dec 27, 2023 12:51 pm

In working on the MariaDB port, I have encountered the following issues:
  • The mkostemp function is documented as accepting additional flags for the open call. In fact, the documentation I have states that the only flags acceptable to this call are O_APPEND, O_SHLOCK, O_EXLOCK and O_CLOEXEC. However, the current VMS implementation requires that all of the flags needed by open be specified.
    • mkostemp(fn, O_CLOEXEC) vs.
    • mkostemp(fn, O_EXCL | O_CREAT | O_RDWR | O_CLOEXEC)
    Will this be changed?
  • Both mkostemp and open accept the O_CLOEXEC flag but do not honor it. Closing a channel opened this way does not delete the file.
  • Many of the open source packages I have worked with open a temporary file (usually with mkstemp) and then call fdopen to get a file pointer. Usually, this call includes the 'b' flag but VMS does not currently open temporary files in binary mode so the fdopen fails. A way to specify binary mode would be greatly appreciated. Something like allowing mkostemp(flags, rms settings) would seem to be ideal.
  • Systems that support O_CLOEXEC also seem to support an 'e' flag (the equivalent of O_CLOEXEC) on calls that take the 'rwb+' flags. Can such support be added?
And a couple of programming questions.

MariaDB is a mix of C and C++ code. It needs to all be compiled with clang because the routines share structures that include both long and size_t items. Standard atomic instructions work fine in C++ code, but what atomic instructions are available for C code? So far, all of my attempts to search for documentation only return results for C++ code. At the moment, all I need are equivalent functions for __LOCK_LONG and __UNLOCK_LONG.

How do I make the following work:
inline void mtr_t::memset(const buf_block_t *b, ulint ofs, ulint len, byte val)
{
lib$signal(SS$_DEBUG);
ut_ad(ofs <= ulint(srv_page_size));
ut_ad(ofs + len <= ulint(srv_page_size));
::memset(ofs + b->page.frame, val, len);
memset(*b, ofs, len, val);
}

While the code compiles fine, it generates a mangled name that resolves to lib$signal(int) which, of course, does not exist in the RTL. I've explicitly defined the function as extern "C" but I haven't been able to convince the compiler to generate a reference to lib$signal instead of _Z10lib$signali.

Any answers or hints anyone can provide will be greatly appreciated.


pustovetov
VSI Expert
Contributor
Posts: 18
Joined: Thu Sep 14, 2023 1:26 am
Reputation: 0
Status: Offline

Re: Some C++/RTL questions

Post by pustovetov » Wed Dec 27, 2023 2:00 pm

mberryman wrote:
Wed Dec 27, 2023 12:51 pm
In working on the MariaDB port, I have encountered the following issues:
  • The mkostemp function is documented as accepting additional flags for the open call. In fact, the documentation I have states that the only flags acceptable to this call are O_APPEND, O_SHLOCK, O_EXLOCK and O_CLOEXEC. However, the current VMS implementation requires that all of the flags needed by open be specified.
    • mkostemp(fn, O_CLOEXEC) vs.
    • mkostemp(fn, O_EXCL | O_CREAT | O_RDWR | O_CLOEXEC)
    Will this be changed?
The Linux manual says: "The mkostemp() function is like mkstemp(), with the difference that flags as for open(2) may be specified in flags (e.g., O_APPEND, O_SYNC)." https://linux.die.net/man/3/mkostemp But of course mkostemp(fn, 0) or mkostemp(fn, O_CLOEXEC) should work. We'll fix it.
  • Both mkostemp and open accept the O_CLOEXEC flag but do not honor it. Closing a channel opened this way does not delete the file.
Could you give a small example? I don't understand what the problem is yet ;(
  • Many of the open source packages I have worked with open a temporary file (usually with mkstemp) and then call fdopen to get a file pointer. Usually, this call includes the 'b' flag but VMS does not currently open temporary files in binary mode so the fdopen fails. A way to specify binary mode would be greatly appreciated. Something like allowing mkostemp(flags, rms settings) would seem to be ideal.
Mode 'b' seems to be supported by the fopen function. Could you please provide a code example for this problem?
  • Systems that support O_CLOEXEC also seem to support an 'e' flag (the equivalent of O_CLOEXEC) on calls that take the 'rwb+' flags. Can such support be added?
This was added in 2020 to the C RTL.


Topic author
mberryman
Active Contributor
Posts: 27
Joined: Sat Sep 02, 2023 1:31 pm
Reputation: 0
Location: Colorado Springs, CO, USA
Status: Offline

Re: Some C++/RTL questions

Post by mberryman » Wed Dec 27, 2023 3:58 pm

Simple reproducer code:
$ type t.c

Code: Select all

#include <unixio.h>
#include <stdio.h>
#include <errno.h>

int main()
{
        char fn1[]="/mariadb_root/tmp/iaXXXXXX";
        char fn3[]="/mariadb_root/tmp/idXXXXXX";
        char fn4[]="/mariadb_root/tmp/idXXXXXX";
        FILE *f1, *f3;
        int i1,i2,i3,i4;
        int mode = O_EXCL | O_CREAT | O_RDWR | O_CLOEXEC;

        i1 = mkostemp(fn1, mode);
        printf("i1 = %d, fn1 = %s\n", i1, fn1);

        mktemp(fn3);
        i3 = open(fn3, mode, 0600, "ctx=bin");
        printf("i3 = %d, fn3 = %s\n", i3, fn3);
        f3 = fdopen(i3, "w+b");
        printf("w+b, f3 = %x\n", f3);

        mktemp(fn4);
        i4 = open(fn4, mode, 0600, "ctx=bin", "fop=dlt");
        printf("i4 = %d, fn4 = %s\n", i4, fn4);

        f1 = fdopen(i1, "w+be");
        printf("w+be, f1 = %x\n", f1);
        if (f1) goto done;

        f1 = fdopen(i1, "w+e");
        printf("w+e, f1 = %x\n", f1);
        if (f1) goto done;

        f1 = fdopen(i1, "w+b");
        printf("w+b, f1 = %x\n", f1);
        if (f1) goto done;

        f1 = fdopen(i1, "w+");
        printf("w+, f1 = %x\n", f1);
done:
        close(i1);
        close(i3);
        close(i4);
        fclose(f1);
        fclose(f3);
}
And the result:
$ run t
i1 = 3, fn1 = /mariadb_root/tmp/ia00013a
i3 = 4, fn3 = /mariadb_root/tmp/id000314
w+b, f3 = 7b73c014
i4 = 5, fn4 = /mariadb_root/tmp/ida00314
w+be, f1 = 0
w+e, f1 = 0
w+b, f1 = 0
w+, f1 = 7b73c010
$ dir mariadb_root:[tmp]

Directory MARIADB_ROOT:[tmp]

IA00013A.;1 ID000314.;1

Total of 2 files.


Three temp files were created but only the file with the explicit "fop=dlt" was deleted on close. The open and mkostemp files with O_CLOEXEC were not.
The reopen function with the flags I've typically seen worked when the file was explicitly opened with "ctx=bin" but failed on all attempts until both the 'b' and 'e' flags were removed when using the mk*temp calls to create the files.


pustovetov
VSI Expert
Contributor
Posts: 18
Joined: Thu Sep 14, 2023 1:26 am
Reputation: 0
Status: Offline

Re: Some C++/RTL questions

Post by pustovetov » Wed Dec 27, 2023 5:10 pm

mberryman wrote:
Wed Dec 27, 2023 3:58 pm
Three temp files were created but only the file with the explicit "fop=dlt" was deleted on close. The open and mkostemp files with O_CLOEXEC were not.
Oh, sorry, but you are wrong. The O_CLOEXEC and FD_CLOEXEC flags are close-on-execute flags rather than delete-on-close. "The FD_CLOEXEC flag associated with the new descriptor shall be set to close the file descriptor upon execution of an exec family function." https://pubs.opengroup.org/onlinepubs/9 ... ntl.h.html
They can be used to prevent the file descriptor inheritance from a parent process. You can read more about what problems these flags should solve, for example, here https://wiki.sei.cmu.edu/confluence/dis ... +processes.
The reopen function with the flags I've typically seen worked when the file was explicitly opened with "ctx=bin" but failed on all attempts until both the 'b' and 'e' flags were removed when using the mk*temp calls to create the files.
Yes, I see bugs in the fdopen routine. It doesn't support 'e' at all and there is some problem with 'b'. Thank you.
p.s. The fopen function should work fine with the 'b' and 'e' flags.


Topic author
mberryman
Active Contributor
Posts: 27
Joined: Sat Sep 02, 2023 1:31 pm
Reputation: 0
Location: Colorado Springs, CO, USA
Status: Offline

Re: Some C++/RTL questions

Post by mberryman » Thu Dec 28, 2023 8:42 am

This will teach me to pay closer attention to the docs and not make assumptions. Thank you for your responses to all of this.

If I may ask, how is O_CLOEXEC implemented? Until an updated RTL is available, I need to write my own version of a few of these routines.


jreagan
VSI Expert
Master
Posts: 139
Joined: Tue Dec 01, 2020 8:40 am
Reputation: 0
Status: Offline

Re: Some C++/RTL questions

Post by jreagan » Thu Dec 28, 2023 10:50 am

According to the POSIX spec and glibc doc, "b" doesn't mean anything to fdopen() [unless I misread the spec].


Topic author
mberryman
Active Contributor
Posts: 27
Joined: Sat Sep 02, 2023 1:31 pm
Reputation: 0
Location: Colorado Springs, CO, USA
Status: Offline

Re: Some C++/RTL questions

Post by mberryman » Thu Dec 28, 2023 2:58 pm

As far as the posix spec is concerned, that would be true. But not all systems folks are writing their code for are posix-compliant. Here is what the Linux man page for fdopen says:
The mode string can also include the letter 'b' either as a last character or as a character between the characters in any of the two-character strings described above. This is strictly for compatibility with C89 and has no effect; the 'b' is ignored on all POSIX conforming systems, including Linux. (Other systems may treat text files and binary files differently, and adding the 'b' may be a good idea if you do I/O to a binary file and expect that your program may be ported to non-UNIX environments.)
As an example, IBM (one of the few remaining platforms that knows what a record is) still documents the 'b' flag as noted here https://www.ibm.com/docs/en/i/7.5?topic ... descriptor

Since VMS is also one of those systems that treats text and binary files differently, wouldn't that indicate that support for the 'b' flag is needed?

In the case of MariaDB, so far all of the instances of fdopen I have encountered are passing a mode of "w+be".


pustovetov
VSI Expert
Contributor
Posts: 18
Joined: Thu Sep 14, 2023 1:26 am
Reputation: 0
Status: Offline

Re: Some C++/RTL questions

Post by pustovetov » Tue Jan 02, 2024 4:28 am

mberryman wrote:
Thu Dec 28, 2023 8:42 am
If I may ask, how is O_CLOEXEC implemented? Until an updated RTL is available, I need to write my own version of a few of these routines.
Do you want to write your fork/exec* routines? The O_CLOEXEC flag only affects these routines.
We don't have a real fork, so this flag behaves a little differently than in Unix.
In Unix, somewhere inside the fork routine, this flag will cause the file/pipe/etc. to be closed. In VMS, exec* routines pass information about open files to a child through a mailbox. If this flag is set, the file is simply skipped.


Topic author
mberryman
Active Contributor
Posts: 27
Joined: Sat Sep 02, 2023 1:31 pm
Reputation: 0
Location: Colorado Springs, CO, USA
Status: Offline

Re: Some C++/RTL questions

Post by mberryman » Tue Jan 02, 2024 2:44 pm

I am hoping not. I have had to write my own open routines (open, fopen, fdopen) and the question I was trying to ask was "what does passing O_CLOEXEC or 'e' to any of these routines cause to be set?". Is it something I can reach or is it strictly internal to the RTL?

It may be a moot point. So far, I have been able to implement my own routines using the C RTL calls with additional RMS settings. As long as I can do that, I can just pass the flags along in the C RTL calls.


pustovetov
VSI Expert
Contributor
Posts: 18
Joined: Thu Sep 14, 2023 1:26 am
Reputation: 0
Status: Offline

Re: Some C++/RTL questions

Post by pustovetov » Wed Jan 03, 2024 2:01 am

mberryman wrote:
Tue Jan 02, 2024 2:44 pm
I am hoping not.
We made our own variants of the vfork/exec routines during the Postgres port. But yeah, it's great "fun".
I have had to write my own open routines (open, fopen, fdopen) and the question I was trying to ask was "what does passing O_CLOEXEC or 'e' to any of these routines cause to be set?". Is it something I can reach or is it strictly internal to the RTL?
This is a very internal part of CRTL. Correctly creating entries in internal file descriptor tables from the outside is not only really difficult but will lead to incompatibility with different versions of the CRTL.
IMO, the better solution is to add the necessary changes to the CRTL.

Post Reply