0

I have a select running on an FDSET which includes a few TCP connections and one unbound UDP connection. In windows, when I close the socket for the UDP connection from a different thread, it signals the select to return. In Ubuntu, however, this is not the case, why?

chacham15
  • 13,719
  • 26
  • 104
  • 207
  • show code or we cannot understand clearly what is being closed. also is your select a select of an array of FD? (file descriptions/sockets) – Noam Rathaus Jan 20 '14 at 20:12
  • from the manual: "It is probably unwise to close file descriptors while they may be in use by system calls in other threads in the same process. Since a file descriptor may be reused, there are some obscure race conditions that may cause unintended side effects" – Karoly Horvath Jan 20 '14 at 20:15
  • @KarolyHorvath noted, but that doesnt seem to be the issue here. the timing of when the socket is closed does not seem to matter. – chacham15 Jan 20 '14 at 20:16
  • @nrathaus the result of a call to `socket()` is what is being closed. the select is on an FDSET which contains a few FDs. – chacham15 Jan 20 '14 at 20:17
  • I think you are doing things that are thread-unsafe, the socket is being closed, but the select() is also on the socket that was just closed right? – Noam Rathaus Jan 20 '14 at 20:22

1 Answers1

2

If this depends on whether you are trying to close the fd during the select, or before the select (and FD_SET). In both cases, for the reasons set out below, the behaviour is undefined. Perhaps it does one thing under Windows, but you cannot rely on it.

If you are trying to close the fd during the select (i.e. after the select() system call has been entered but before it returns), then the behaviour is undefined for the reasons set out here: What does select(2) do if you close(2) a file descriptor in a separate thread?

If you are trying to close the fd before the select (and FD_SET), then you are trying to FD_SET then select() on an FD that is now closed, i.e. is invalid. The standard is here: http://pubs.opengroup.org/onlinepubs/009695399/functions/select.html and this says that the FD_SET macro may not even be asking select() to look at your FD.

The behavior of these macros is undefined if the fd argument is less than 0 or greater than or equal to FD_SETSIZE, or if fd is not a valid file descriptor, or if any of the arguments are expressions with side effects.

If it does (and only if it does), select should be returning EBADF:

Under the following conditions, pselect() and select() shall fail and set errno to:

[EBADF] One or more of the file descriptor sets specified a file descriptor that is not a valid open file descriptor.

But you have no way of knowing that will be the case, as FD_SET might equally just ignore the invalid file descriptor.

For completeness, if you do the FD_SET before the close, but then do the select, you should see EBADF.

Community
  • 1
  • 1
abligh
  • 24,573
  • 4
  • 47
  • 84
  • No, the closing of the FD is tied to my pressing of a button. Therefore, I am 100% sure that at the time of the call to select, the FD is valid. – chacham15 Jan 20 '14 at 20:42
  • So it's *in* the `select()` when you close the fd? In that case, the behaviour of `select()` itself is not defined by the POSIX standard (see the link I sent). IE it might return, it might not. See: http://stackoverflow.com/questions/543541/what-does-select2-do-if-you-close2-a-file-descriptor-in-a-separate-thread – abligh Jan 20 '14 at 20:43
  • As far as I can tell, that link says nothing about the socket being closed after the call. Did I miss something? – chacham15 Jan 20 '14 at 20:47
  • It's talking about the select being closed *during* the call. If the close is done *after* the call, then the `select()` has already returned. – abligh Jan 20 '14 at 20:53
  • If you modify your answer to include the referenced material, Ill mark it as correct. – chacham15 Jan 20 '14 at 20:59
  • @chacham15 There is no such thing as "at the time of the call to select". When you call `select`, the system can take as long as it wants before it actually does any particular thing. No matter how long it is after you think you called `select`, so long as `select` has not yet returned there is in general no way to know whether or not it's actually done anything yet or whether it's about to start doing things. (If you think there is, explain how.) – David Schwartz Jan 20 '17 at 19:46
  • @chacham15 The question specifically talks about closing the socket from another thread. There is no way for that other thread to know whether `select` has started yet or is about to start. Say thread A calls `select`. There is no way for thread B to know whether thread A is about to start the `select` but not yet done anything, or blocked in `select`. If you think there is a way, explain it. – David Schwartz Jan 24 '17 at 18:07
  • @DavidSchwartz thats not the point of the question. If close executes before select, then the select will fail. The question is asking about *IF* the close happens after the select, what happens / why. – chacham15 Jan 26 '17 at 22:29
  • @chacham15 Actually, it's incorrect to say that the `select` will fail. The results are unpredictable in that case (because, among other reasons, the socket may be reused). And the point is, even if there was guaranteed behavior if the close happens after the select, since it's impossible to guarantee the close happens after the select, a guarantee that only applied in cases you had no guarantee would occur would be utterly meaningless. – David Schwartz Jan 26 '17 at 23:01
  • @chacham15 Let me put it this way: Suppose case X has unpredictable behavior. That means anything that might be case X also has unpredictable behavior. Now, `close` before `select` has unpredictable behavior. Therefore anything that might be `close` before `select` has unpredictable behavior. There is no way to `close` after `select` without possibly closing before `select`. So any close after might be close before and thus has unpredictable behavior. – David Schwartz Jan 26 '17 at 23:07