-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
HCI Bluetooth socket bind error on an arm crosscompiled environment #67632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This bug bellow occurs only on my crosscompiled environment on arm (marvell armada 166): arm-pxa168-linux-gnueabi description and first clues The problem is easyly reproducted using this script: #!/usr/bin/python
import socket
sock = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI)
sock.bind((0,)) which raises the following exception when run on the target device: Traceback (most recent call last):
File "./test_bt.py", line 4, in <module>
sock.bind((0,))
OSError: [Errno 22] Invalid argument This does not give much clues, but strace does (i've filtered to display the
(on a working environment, including arm, like a raspberry pi, strace gives the following result (and no traceback of course):
So, on the armada166, between the socket creation and the bind we lost the socket family (AF_UNSPEC instead of AF_BLUETOOTH). And That's why bind returns invalid argument. socketmodule and PyArg_ParseTuple Now let's look at Modules/socketmodule.c: After some digging, i've found that the problem is in getsockaddrarg, in the AF_BLUETOOTH / BTPROTO_HCI case
reproducted here: if (!PyArg_ParseTuple(args, "i", &_BT_HCI_MEMB(addr, dev))) { When we execute the PyArg_ParseTuple, the addr->hci_family is crunched (by zeros with my previous python sample). At this same place, i've done the following test: char buffer[8];
memset(buffer, 0x55, 8);
if (!PyArg_ParseTuple(args, "i", buffer) {
PyErr_SetString(PyExc_OSError, "getsockaddrarg: "
"wrong format");
return 0;
}
printf("CL: %d %d %d %d %d %d %d %d\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]);
memset(buffer, 0xAA, 8);
if (!PyArg_ParseTuple(args, "i", buffer+1) {
PyErr_SetString(PyExc_OSError, "getsockaddrarg: "
"wrong format");
return 0;
}
printf("CL+1: %d %d %d %d %d %d %d %d\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]);
memset(buffer, 0xBB, 8);
if (!PyArg_ParseTuple(args, "i", buffer+2) {
PyErr_SetString(PyExc_OSError, "getsockaddrarg: "
"wrong format");
return 0;
}
printf("CL+2: %d %d %d %d %d %d %d %d\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]);
memset(buffer, 0xcc, 8);
if (!PyArg_ParseTuple(args, "i", buffer+3) {
PyErr_SetString(PyExc_OSError, "getsockaddrarg: "
"wrong format");
return 0;
}
printf("CL+3: %d %d %d %d %d %d %d %d\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]); and the result is:
(WTF ??) in a working environnement (tested on raspberry B+ / python 3.4.2 locally compiled) result is what we should expect:
So on my box if PyArg_ParseTuple write on &addr->hci_dev if write 4 bytes from &addr->hci_family which is 2 bytes BEFORE &addr->hci_dev At this time I can not understand how it's possible. Remarks and patch Now I have several remarks and a working patch.
in Python/getargs.c, in convertsimple, int parsing result is not casted before returned: here: https://hg.python.org/cpython/file/ab2c023a9432/Python/getargs.c#l690 (ival is a long). In all other cases (short, unsigned short, char, usigned char), they are casted before return.
--- Python-3.4.2/Modules/socketmodule.c 2014-10-08 10:18:15.000000000 +0200
+++ CC_PYTHON/Python-3.4.2/Modules/socketmodule.c 2015-02-11 15:42:35.173455634 +0100
@@ -1446,11 +1446,12 @@ getsockaddrarg(PySocketSockObject *s, Py
return 0;
#else
_BT_HCI_MEMB(addr, family) = AF_BLUETOOTH;
- if (!PyArg_ParseTuple(args, "i", &_BT_HCI_MEMB(addr, dev))) {
+ if (!PyArg_ParseTuple(args, "H", &_BT_HCI_MEMB(addr, dev))) {
PyErr_SetString(PyExc_OSError, "getsockaddrarg: "
"wrong format");
return 0;
}
+ _BT_HCI_MEMB(addr, channel) = HCI_CHANNEL_RAW;
#endif
*len_ret = sizeof *addr;
return 1; in short: I parse now an unsigned short instead of parsing an int which gives me a two bytes long elements which is stored well But this modification alone is not enough: addr->hci_channel needed a good value. And that led me to another question/problem: how is hci_channel normally handled ? |
It should be fixed by #131668. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: