On Wed, 6 Feb 2008 08:13:45 -0800 (PST) David Schwartz <***@webmaster.com> wrote:
| On Feb 6, 6:22 am, phil-news-***@ipal.net wrote:
|
|> A process starts thread A which creates a descriptor to somewhere that
|> will appear to be ready to receive data, but never will, such as a TCP
|> connection to some "server" that never sends any data. The descriptor
|> number is stored somewhere so thread B can get it. Thread B is started.
|> Thread B goes to sleep for 1 HOUR. Thread A does a poll() call on that
|> descriptor, checking for read data, with a timeout value of 1 WEEK.
|> After 1 HOUR of sleeping, thread B wakes up and closes the descriptor.
|> If there is an error from close() it reports it. Then thread B quits.
|> Whenever thread A returns from poll(), be that immediate, or near when
|> the the close happened, or a week later, it checks the return codes,
|> errno, and the status in the poll list. It also checks to see if it
|> was in the poll() call for less than the timeout specified. My idea
|> for the standard is for the scenario in question to set an error status
|> like POLLERR for the descriptor involved. Thread A checks for errors
|> that poll() call returned. If it get EBADF it reports that it failed to
|> reach the poll() call in a timely manner and that thread B's one hour
|> delay needs to be extended on this way too slow system. Otherwise it
|> reports whether it woke up with POLLERR on the descriptor or not.
|
| That doesn't work. If it gets 'EBADF' it has no way to know which of
| the following two scenarios occurred:
|
| 1) The scheduler chose to delay the thread for a very long time, as it
| has every right to do, and it still managed to sneak in the 'close'
| before the 'poll', or
|
| 2) The 'close' occurred during the 'poll', and the platform chose to
| act as if the 'poll' was delayed by returning 'EBADF'.
Either way, the platform is presenting the same concept. Acting as if
the close occurred before is equivalent as if it had actually happened.
If this is the error you get, it won't matter.
|> | Try it, it's impossible.
|
|> It's way too simple for me to even put in the effort. I know it can be
|> done.
|
| Then do it. Tell me how you distinguish case 1 from case 2 above.
You don't need to.
|> | You are correct that if you could know that you had succeeded, the
|> | standard could specify what happens in that case. But you can't even
|> | know that you succeeded.
|
|> If the poll() call returns EBADF then the poll() did run AFTER that
|> descriptor was closed.
|
| No, the 'poll' could have run before the descriptor was closed and the
| platform decided to act as if the 'poll' had run after, knowing that
| the program cannot tell the difference between these two cases.
|
| Try again.
Your logic ... that a platform could choose to do the wrong thing and
give the wrong perception ... could be applied to just about every
interface that is standardized. For example, even though a file does
exist, the platform could decide to act as if it does not and give an
open(,O_RDONLY) an ENOENT error. Even though the file could actually
exist, the platform is _pretending_ that it does not. This does not
mean we cannot have standards for the open() syscall.
|> If poll() successfully enters, then that
|> descriptor was still open at the time poll() runs, and the scenario
|> is under test.
|
| But you can't tell whether poll successfully enters or not. How can
| you tell?
You can tell if the platform wants to let you think it. If the platform
decides to fake a scenario different that actually happened, this is
very much possible for just about anything.
|> | Keep in mind, the implementation may open and close files, pipes, and
|> | sockets behind your back at any time. If you 'close' a descriptor, it
|> | is always possible for the pthreads implementation itself to open
|> | something and get that same descriptor.
|
|> The "implementation" is the kernel.
|
| No. The implementation is everything needed to provide the functions
| the standard asks for. This includes the pthreads library.
One can do these things without the pthreads library. So what if the
way of doing them is not standard. We don't have to define how the
descriptor got closed ... only that it does. So what if a process
calls the Linux specific clone() syscall with CLONE_FILES set, to make
raw threads.
|> Why would the kernel do that?
|
| Well, let's say when you call 'pthread_create' it starts a monitor
| thread. Let's say that monitor threads runs from time to time to check
| on threads that need to be reaped and other such things. It's possible
| that monitor thread might need to open a file, maybe a system log file
| to report on memory usage, who knows?
To create a proper test program for a kernel interface, you can be sure
I would not use pthreads. And what you described is not the only reason
for such a decision on how to design a test module for this as part of
a robust test suite.
|> Just
|> because the standards says that is not defined? I think we can REASONABLY
|> assume a REASONABLE kernel that does not just make up descriptors.
|
| No, we can't assume that. POSIX-defined library functions open
| descriptors all the time. If you call "gethostbyname" and DNS is used,
| it's not unreasonable that a persistent TCP connection might be opened
| up to the nameserver, for example.
|
|> Who
|> said anything about using pthreads in a test program? It is not pthreads
|> that would be tested, it is the kernel syscall layer. And the test program
|> itself would not be coded to risk its own test by trying to do any other
|> open calls (or dup or whatever).
|
| So you're saying perhaps the standard should guarantee a particular
| behavior for processes that don't use pthreads even though it can't
| keep that guarantee for processes that don't? There is no relevant
| multi-threading standard other than pthreads for multiple-threads on
| systems that even support 'poll', so now you're talking about
| guarantees on a hypothetical platform that doesn't apply to any real-
| world platform?
A thread is merely a way to get a descriptor to be closed. We could also
force it closed by adding a facility to do that in some other way. The
point is, the proposal I suggest for poll/select behaviour when one or
all of the descriptors is closed is not based on _how_ it gets closed,
but rather, that it does get closed, however that may be. A variant of
pthreads that chooses not do open anything the main program does not do
explicitly could be used as a test basis. Or one can just not use the
pthreads library at all.
| You're way out there now.
I'm outside the box.
| For practical purposes, we're talking about what POSIX threads say
| about what happens when on thread calls 'close' on a descriptor while
| another thread is, or is about to, call 'poll' on it.
Almost.
--
|---------------------------------------/----------------------------------|
| Phil Howard KA9WGN (ka9wgn.ham.org) / Do not send to the address below |
| first name lower case at ipal.net / spamtrap-2008-02-06-***@ipal.net |
|------------------------------------/-------------------------------------|