title: Bluetooth RFCOMM socket is not writable while another socket is connecting (Linux, blueZ, C++)
body: <p>I am implementing a C++ program that communicates via Bluetooth RFCOMM with several different robots via bluetooth. In this communication scenario the robots are servers and my program consists of several clients.</p>
  
  <p>I implemented two threads:
  <strong>1.</strong> the ConnectThread connects to several servers via different sockets. The connections are established one after the other. If a connection is lost, it will be reestablished later.
  <strong>2.</strong> the DataSendThread sends data to all connected servers via their sockets.</p>
  
  <p><strong>Problem:</strong>
  If the DataSenThread is currently sending data via Socket A and a new connection is being established in the Connect thread via Socket B, then Socket A is not writable for a few seconds.
  But for my application I need a continuous connection to the robots.</p>
  
  <p>I use several Bluetooth interfaces. The application requires that the connections to the servers are distributed to multiple Bluetooth interfaces. Therefore, before 'connect' to the socket, a specific Bluetooth interfaces is assigned to the socket using 'bind'. Each socket that is assigned to a Bluetooth interfaces has its own port.</p>
  
  <p>All objects used by both threads are passed as std::shared_ptr.</p>
  
  <p>Because of the complexity I show the program as pseudo code:</p>
  
  <pre><code>ConnectThread:
  1. search for available bt-servers ('hci_inquiry')
  2. for each available bt-servers:
    if available bt-server is new
      create a new bt-server object
    if bt-server is not connected
      2.1 choose the bt-interfaces with the fewest connections
      2.2 create a socket (socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM))
      2.3 make socket nonblocking ('fcntl')
      2.4 bind the choosen bt-interfaces to the socket ('bind')
      2.5 connect socket nonblocking ('connect')
      2.6 wait for the connection to be established ('select')
  
  
  DataSendThread:
  1. for each connected bt-server:
    1.1 if socket writeable ('select')
      1.1.1 send data ('send')
  </code></pre>
  
  <p>Does anyone have an idea why the connection of one socket affects the existing connection of another socket?</p>
  
  <p>Thanks a lot!</p>
  
  <p><strong>Edit:</strong> </p>
  
  <p>The problem only occurs if the two servers are connected via the same Bluetooth interface. If they are connected via different Bluetooth interfaces, there is no interference. My guess is that the Bluetooth interface is very busy during the connection process and therefore neglects already existing connections of other sockets. Is this possible?</p>
  
  <p><strong>Edit2:</strong>
  Here is a kind of minimal example that produces the problem:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;thread&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;bluetooth/bluetooth.h&gt;
  #include &lt;bluetooth/rfcomm.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;cstring&gt;
  
  struct sockaddr_rc server1_addr = { 0 };
  struct sockaddr_rc server2_addr = { 0 };
  int socketServer1;
  int socketServer2;
  int portToLocalBtAdapter = 1;
  int toggleData = 0;
  bool stopThread = false;
  
  int connectToServer(struct sockaddr_rc* server_addr){
      char serverAddrStr[19];
      ba2str(&amp;(server_addr-&gt;rc_bdaddr),serverAddrStr);
  
      //valid RFCOMM Ports: 1..31
      if(portToLocalBtAdapter &gt; 31)
          return -1;
  
      //local bluetooth adapter
      struct sockaddr_rc local_addr = { 0 };
      bdaddr_t bdaddr_any =  {{0, 0, 0, 0, 0, 0}};
      local_addr.rc_family = AF_BLUETOOTH;
      local_addr.rc_bdaddr = bdaddr_any;
      local_addr.rc_channel = (uint8_t) portToLocalBtAdapter; 
  
      int sock;
      if((sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) &lt; 0)
          return -1;
  
      if(bind(sock, (struct sockaddr *)&amp;local_addr, sizeof(local_addr)) &lt; 0)
          return -1;
  
      socklen_t sOfServer = sizeof(*server_addr);
      std::cout &lt;&lt; "connect begin" &lt;&lt; std::endl;
      if(connect(sock, (struct sockaddr *)server_addr, sOfServer) &lt; 0)
          return -1;
      std::cout &lt;&lt; "connect end" &lt;&lt; std::endl;
  
      //check if there is an socket error (e.g. "Host is down")
      int error = 0;
      socklen_t len = sizeof(error);
      getsockopt(sock, SOL_SOCKET, SO_ERROR, &amp;error, &amp;len);
      if(error){
          errno = error;
          return -1;
      }
      std::cout &lt;&lt; "Connected socket " &lt;&lt; sock &lt;&lt; " to server "&lt;&lt; serverAddrStr &lt;&lt; " using port " &lt;&lt; +local_addr.rc_channel &lt;&lt; " of local bt adapter." &lt;&lt; std::endl;
  
      //every server connection gets its own port to local bt adapter
      portToLocalBtAdapter++;
      return sock;
  }
  
  void sendThread(){
      while(!stopThread){
          fd_set wset;
          FD_ZERO(&amp;wset);
          FD_SET(socketServer1, &amp;wset);
          struct timeval  tval;
          tval.tv_sec = 1; //1s timeout
          tval.tv_usec = 0;
          int ret;
          //check if socketServer1 is writeable within 1s
          if((ret = select(socketServer1+1, NULL, &amp;wset, NULL, &amp;tval)) &gt; 0){
              //tval contains the remaining time until timeout
              double blockingTime = 1.0 - ((double)tval.tv_sec+((double)tval.tv_usec)/1000000.0);
              if(blockingTime &gt; 0.001)
                  std::cout &lt;&lt; "send on socket " &lt;&lt; socketServer1 &lt;&lt; " blocked for " &lt;&lt; blockingTime &lt;&lt;"s"&lt;&lt; std::endl;
  
              //data to send, red and blue LED blinking
              uint8_t redData[]  =  {255,255,2,32,160,5,255,0,0,0,57};
              uint8_t blueData[]  = {255,255,2,32,160,5,0,0,255,0,57};
              uint8_t* dataToSend;
              if(toggleData++ % 2)
                  dataToSend = redData;
              else
                  dataToSend = blueData;
  
              if(send(socketServer1, dataToSend, 11 , 0) &lt; 0)
                  std::cout &lt;&lt; "send failed on socket " &lt;&lt; socketServer1 &lt;&lt; std::endl;  
          }
          else
              std::cout &lt;&lt; "socket " &lt;&lt; socketServer1 &lt;&lt; " not writeable, ret = " &lt;&lt; ret &lt;&lt; std::endl;  
          usleep(33000); //33ms
      }
  }
  
  
  int main(int argc, char** argv){
      server1_addr.rc_family = AF_BLUETOOTH;
      str2ba("68:86:E7:09:71:87", &amp;server1_addr.rc_bdaddr );
      server1_addr.rc_channel = (uint8_t) 1;
  
      server2_addr.rc_family = AF_BLUETOOTH;
      str2ba("68:86:E7:07:4C:19", &amp;server2_addr.rc_bdaddr );
      server2_addr.rc_channel = (uint8_t) 1;
  
      std::cout &lt;&lt; "Try to connect server 1" &lt;&lt; std::endl;
      while((socketServer1 = connectToServer(&amp;server1_addr)) &lt; 0){
          std::cout &lt;&lt; "connect to server 1 failed: "&lt;&lt; std::strerror(errno) &lt;&lt; std::endl;
          usleep(1000000); //1s
      }
  
      std::cout &lt;&lt; "start sending data to server 1" &lt;&lt; std::endl;
      std::thread sendThrd(&amp;sendThread);
      usleep(3000000); //3s
  
      std::cout &lt;&lt; "Try to connect server 2" &lt;&lt; std::endl;
      while((socketServer2 = connectToServer(&amp;server2_addr)) &lt; 0){
          std::cout &lt;&lt; "connect to server 2 failed: "&lt;&lt; std::strerror(errno) &lt;&lt; std::endl;
      }
      usleep(3000000); //3s
      stopThread = true;
      sendThrd.join();
      std::cout &lt;&lt; "stopped sending data to server 1" &lt;&lt; std::endl;
      close(socketServer1);
      close(socketServer2); 
      return 0;
  }
  </code></pre>
  
  <p>The output is:</p>
  
  <pre><code>Try to connect server 1
  connect begin
  connect end
  Connected socket 4 to server 68:86:E7:09:71:87 using port 1 of local bt adapter.
  start sending data to server 1
  Try to connect server 2
  connect begin
  send on socket 4 blocked for 0.060255s
  send on socket 4 blocked for 0.100941s
  send on socket 4 blocked for 0.035571s
  send on socket 4 blocked for 0.039356s
  send on socket 4 blocked for 0.105597s
  send on socket 4 blocked for 0.03558s
  send on socket 4 blocked for 0.039496s
  send on socket 4 blocked for 0.105447s
  send on socket 4 blocked for 0.035594s
  send on socket 4 blocked for 0.039317s
  send on socket 4 blocked for 0.105614s
  send on socket 4 blocked for 0.035575s
  send on socket 4 blocked for 0.039457s
  send on socket 4 blocked for 0.105492s
  send on socket 4 blocked for 0.035557s
  send on socket 4 blocked for 0.105619s
  send on socket 4 blocked for 0.104394s
  send on socket 4 blocked for 0.104443s
  send on socket 4 blocked for 0.035453s
  send on socket 4 blocked for 0.039335s
  send on socket 4 blocked for 0.105745s
  send on socket 4 blocked for 0.035549s
  send on socket 4 blocked for 0.03926s
  send on socket 4 blocked for 0.033224s
  send on socket 4 blocked for 0.026101s
  send on socket 4 blocked for 0.03556s
  send on socket 4 blocked for 0.039261s
  send on socket 4 blocked for 0.105614s
  send on socket 4 blocked for 0.035519s
  send on socket 4 blocked for 0.03935s
  send on socket 4 blocked for 0.10563s
  send on socket 4 blocked for 0.054211s
  connect end
  Connected socket 6 to server 68:86:E7:07:4C:19 using port 2 of local bt adapter.
  stopped sending data to server 1
  
  
  </code></pre>
  
  <p>The socket is often not writable for up to 105ms in a period of 2-3s (while connecting the other socket). Interestingly, the behavior does not change even if portToLocalBtAdapter is not increased. This will cause all sockets to communicate with the Bluetooth Adapter over the same port, right?</p>