Operating System - HP-UX
1832152 Members
3376 Online
110038 Solutions
New Discussion

HP-UX B.11.11 catgets() function - inherited file descriptor

 
SOLVED
Go to solution
Shane Hird
Occasional Advisor

HP-UX B.11.11 catgets() function - inherited file descriptor

It appears the catgets() function on HP-UX B.11.11 PA-RISC does not handle sharing a file descriptor between processes. Calling the function simultaneously with the same file descriptor in seperate processes can result in the wrong message being returned.

Other platforms do not suffer from this problem. Presumably they perform a dup() on the handle on entry to the catgets() function.

Is this error expected behaviour or a bug with the OS? I am yet to work out how to raise the bug with HP.

Please see the attached file for an example.
13 REPLIES 13
Dennis Handly
Acclaimed Contributor

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

I would have to test this out but it seems there are two issues.
1) Sharing of the FD. This could fail if the file pointer is shared.
2) Sharing of the return buffer. This is the likely cause. Since this limitation is documented, you'll have to use your own locking primitives.
Shane Hird
Occasional Advisor

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

I would have thought the static buffer would be per process only. ie. doing something like:

fd = catopen("CAT")
char *lmsg1 = catgets(fd, 1)
char *lmsg2 = catgets(fd, 2)
printf("%s%s", lmsg1, lmsg2)

would be invalid, as each call would overwrite the buffer. However... doing:

fd = catopen("CAT")
if (fork())
char *lmsg1 = catgets(fd, 1)
printf("%s", lmsg1)
else
char *lmsg2 = catgets(fd, 2)
printf("%s", lmsg2)
end if

should be ok, as each catgets() call would be using a different buffer in a different process - and it actually does work ok on other platforms. It fails on HP-UX because sometimes the message returned is different. I suspect this is because the implementation of catgets() is changing the offset in the fd in one process, which is reflected in the other.

Perhaps what catgets() be doing is something like:

char* catgets(fd, id) {
ltmpfd = dup(fd)
seek(ltmpfd, id)
return fread(ltmpfd)
}

This appears to be what other platforms do, as they don't suffer the same problem.

It is debatable whether the catgets() implementation needs to support shared file descriptors, but I need an offical word from HP as to whether this is a bug or not.
Dennis Handly
Acclaimed Contributor

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

>I would have thought the static buffer would be per process only.

Oops, I was thinking of vfork.

>I suspect this is because the implementation of catgets() is changing the offset in the fd in one process, which is reflected in the other.

Most likely. If so, it seems that this is expected, as in all cases of sharing a FD with forked processes.

>Perhaps what catgets() be doing is something like:

I would hope they close ltmpfd. ;-)

Hmm, reading dup(2) indicates that:
both file descriptors share one file pointer

So dup(2) won't help.

>It is debatable whether the catgets() implementation needs to support shared file descriptors, but I need an official word from HP as to whether this is a bug or not.

You have just answered your question. If debatable, it won't be changed. The best that can be done is beef up the man page and add your picture. :-)
With a comment that says you must call catopen(3) in the CURRENT process. There are some words about valid until exec functions and close-on-exec flag.
Shane Hird
Occasional Advisor

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

>Hmm, reading dup(2) indicates that:
>both file descriptors share one file pointer

>So dup(2) won't help.

Perhaps they use some other means to duplicate the handle, or just locking on the handle. But the point being they have some kind of guard against the problem, which HP-UX doesn't have.

It's interesting to note HP implies that catgets() is thread safe:
http://docs.hp.com/en/B2355-60105/thread_safety.5.html

which seems unusual given it uses a static buffer, and can't use the same fd at the same time.

I'd be happy to close and re-open the catalog file after the fork, but the handle is opened and used in a 3rd party library.

I guess I will have to raise the issue with HP, but its a lot of work to go through to get the inevitable "working as designed" just to show the 3rd party vendor that they need to change their code.

I appreciate the input, thanks for your help.
Dennis Handly
Acclaimed Contributor

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

>It's interesting to note HP implies that catgets() is thread safe:

That part is easy. ;-)

>which seems unusual given it uses a static buffer, and can't use the same fd at the same time.

It probably uses a TLS buffer if it detects it is threaded. And would have to lock a mutex to protect the FD.

>I'd be happy to close and re-open the catalog file after the fork, but the handle is opened and used in a 3rd party library.

Why would the library care what you did? You'll put it back at the same FD using open(2) dup2(2) close(2).

>I guess I will have to raise the issue with HP

You could at least ask them to improve the documentation if it isn't a bug.
Shane Hird
Occasional Advisor

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

> Why would the library care what you did?
> You'll put it back at the same FD using
> open(2) dup2(2) close(2).

I'm not sure I follow. Perhaps you're assuming our code is opening the handle? We are using a 3rd party library which does the catopen, catgets etc internally. eg.

our code:
int main() {
init()
work()
term()

fork()

init()
work()
term()
}

3rd party library code:
void init() {
fd = catopen()
}
void term() {
// no close
}
void work() {
catgets(fd)
}
Dennis Handly
Acclaimed Contributor

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

>Perhaps you're assuming our code is opening the handle? We are using a 3rd party library which does the catopen, catgets etc internally.

Or you know the name of the global that contains the FD? If it is a static, that's going to be a problem.
Shane Hird
Occasional Advisor

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

Sorry I should have mentioned, it's a closed source library. If it was open we'd just change the code ourself :)
Dennis Handly
Acclaimed Contributor
Solution

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

>it's a closed source library.

Well, you could put a breakpoint in catopen and find where it puts it.

Or you can create a stub for catopen, use dlsym to find the real one, call it, cache the FD and then return.
Shane Hird
Occasional Advisor

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

Thanks, I'll keep those tricks in mind if it gets desperate. But I doubt that would pass our review process :) We have a support contract with both HP and the vendor, so hopefully one will deliver a proper fix for us - it's just a matter of who is responsible for the problem :)
Dennis Handly
Acclaimed Contributor

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

I took a look at catgets and it has a mutex for the searching in the thread case. I suppose this could be removed and atomic pread used instead. But this is only available on 11.23 and on.
Shane Hird
Occasional Advisor

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

Thanks for taking a look. We have raised the case with HP who have reported this as a known problem - with the workaround to close the handle before forking. Unfortuantly this doesn't help us in our case. Hopefully they can work something out for us.
Dennis Handly
Acclaimed Contributor

Re: HP-UX B.11.11 catgets() function - inherited file descriptor

>who have reported this as a known problem

Hmm, I just found a real old defect that was closed:
QXCR1000475401: catgets fails when coupled with fork'd process