classification
Title: socket's SO_OOBINLINE option does not work
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.0, Python 2.6, Python 2.5
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: gregory.p.smith Nosy List: giampaolo.rodola, gregory.p.smith
Priority: normal Keywords:

Created on 2008-07-04 02:18 by giampaolo.rodola, last changed 2008-07-06 19:36 by gregory.p.smith. This issue is now closed.

Messages (6)
msg69237 - (view) Author: Giampaolo Rodola' (giampaolo.rodola) * (Python committer) Date: 2008-07-04 02:18
When the SO_OOBINLINE option is used against a socket, out-of-band data
should be placed in the normal data input stream as it is received.
In fact this is what happens on Windows and Linux by using the script below.
On FreeBSD this does not happen. select instead of returning a
"readable" file descriptor returns an "exceptional" file descriptor. 
Later, when we try to read some data from the socket, the following
exception is raised:


Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/local/lib/python2.5/threading.py", line 460, in __bootstrap
    self.run()
  File "/usr/local/lib/python2.5/threading.py", line 440, in run
    self.__target(*self.__args, **self.__kwargs)
  File "_test2.py", line 14, in server
    data = conn.recv(1024, socket.MSG_OOB)
error: (22, 'Invalid argument')





--- code ---

import socket, select, threading, time, os

def server():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('', 1024))
    s.listen(1)
    conn, addr = s.accept()
    conn.setblocking(0)
    conn.setsockopt(socket.SOL_SOCKET, socket.SO_OOBINLINE, 1)
    while 1:
        r, w, e = select.select([conn], [conn], [conn], 0.01)
        if r:
            # the socket is supposed to be in the "readable" list
            data = conn.recv(1024)
            print "read -> " + data
        if e:
            # ...but not in the "exception" list
            data = conn.recv(1024, socket.MSG_OOB)
            print "expt -> " + data


threading.Thread(target=server).start()
time.sleep(0.1)
s = socket.socket()
s.connect(('127.0.0.1', 1024))
s.sendall('x', socket.MSG_OOB)

--- /code ---
msg69238 - (view) Author: Giampaolo Rodola' (giampaolo.rodola) * (Python committer) Date: 2008-07-04 02:19
This bug should be strictly related with issue 3277:
http://bugs.python.org/issue3277
msg69343 - (view) Author: Gregory P. Smith (gregory.p.smith) * (Python committer) Date: 2008-07-06 17:20
This also happens on Linux:

read -> x
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/home/greg/sandbox/python/trunk/Lib/threading.py", line 523, in
__bootstrap_inner
    self.run()
  File "/home/greg/sandbox/python/trunk/Lib/threading.py", line 478, in run
    self.__target(*self.__args, **self.__kwargs)
  File "../socket_oobinline.py", line 20, in server
    data = conn.recv(1024, socket.MSG_OOB)
error: [Errno 22] Invalid argument


I need to look up what the exact behavior should be.
msg69350 - (view) Author: Gregory P. Smith (gregory.p.smith) * (Python committer) Date: 2008-07-06 18:44
p648 of Unix Network Programming third edition:

"4. If the process has set the SO_OOBINLINE socket option and then tries
to read the out-of-band data by specifying MSG_OOB, EINVAL is returned."

so it does not sound like a bug in Python.

There -does- appear to be a difference in BSD and Linux's socket
implementation here.  select returned the socket in both the read and
exception list on Linux.  While on BSD it only returned it in the
exception list.

The application is presumably supposed to keep track of which sockets it
has set SO_OOBINLINE on to know what to do when select returns them in
the exception state.

That said... OS X (and presumably FreeBSD) behaves oddly.  The socket is
only ever returned in the e list and an attempt to conn.recv(1) from it
raises socket.error "error: [Errno 35] Resource temporarily unavailable"
msg69352 - (view) Author: Gregory P. Smith (gregory.p.smith) * (Python committer) Date: 2008-07-06 19:34
further reading reveals that this is the expected behavior.

p651 in 24.2: "select indicates an exception condition until the process
reads -beyond- the out of band data."  ...  "the solution is to only
select for an exception condition after reading normal data."  with code
examples.

in short: if you want OOB with select there are hoops to jump through
for the edge cases.  its layed out in the book.
msg69353 - (view) Author: Gregory P. Smith (gregory.p.smith) * (Python committer) Date: 2008-07-06 19:36
A friend confirms that on NetBSD it matches the Linux behavior.

"read -> x" is printed before the exception.

also fwiw, my OS X version is 10.5.3.

IMNSHO not a python bug.  open it with FreeBSD and Apple.
History
Date User Action Args
2008-07-06 19:36:00gregory.p.smithsetstatus: open -> closed
resolution: not a bug
messages: + msg69353
2008-07-06 19:34:43gregory.p.smithsetmessages: + msg69352
2008-07-06 18:44:34gregory.p.smithsetmessages: + msg69350
2008-07-06 17:20:49gregory.p.smithsetmessages: + msg69343
title: socket's SO_OOBINLINE option does not work on OS X and FreeBSD -> socket's SO_OOBINLINE option does not work
2008-07-06 17:14:04gregory.p.smithsetpriority: normal
assignee: gregory.p.smith
title: socket's SO_OOBINLINE option does not work on FreeBSD -> socket's SO_OOBINLINE option does not work on OS X and FreeBSD
nosy: + gregory.p.smith
2008-07-04 11:42:43giampaolo.rodolasettitle: socket's SO_REUSEADDR option does not work on FreeBSD -> socket's SO_OOBINLINE option does not work on FreeBSD
2008-07-04 02:19:02giampaolo.rodolasetmessages: + msg69238
2008-07-04 02:18:00giampaolo.rodolacreate