This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NRF9160 BSD socket "send function" isn't blocked.

I use BSD socket to send and receive messages to a TCP server over LTE network.

When I send multiple messages by using send() (with flags = 0) function, I get an EINPROGRESS error.
It seems that send() function is not blocked.


I'm currently using the v1.1.0 release.

How can I fix this problem?

Parents
  • Hi,

     

    There are certain use-cases where send() isn't blocking, which are mentioned in the changelog:

    http://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrfxlib/bsdlib/doc/CHANGELOG.html

     

    Could you share the routine that you're running?

     

    Kind regards,

    Håkon

  • ERROR_STATUS blocking_send(int sock, u8_t *buf, u32_t datalen, u32_t flags, uint32_t timeout)
    {
         u32_t offset = 0U;
         int ret;
         s64_t time_stamp = k_uptime_get();
         s64_t milliseconds_spent = 0;

         while ((offset < datalen)&&(milliseconds_spent <timeout))
                 {
                     ret = send(sock, buf + offset,
                                        MIN(4096, (datalen - offset)), flags);
                     if (ret < 0)
                        {
                            return -errno;
                         }

                        offset += ret;
                       milliseconds_spent += k_uptime_delta(&time_stamp);
                 }
           if(milliseconds_spent >= timeout)
                  return STATUS_TIMEOUT;
           return 0;
    }

  • Hi,

    No, I have only one thread that uses the modem.

    Attached is a source code that describes this thread.

    Meni

    ERROR_STATUS server_connect(uint8_t* url, uint16_t port, int *client_fd)
    {
      ERROR_STATUS err_state;
      err_state = modem_configure();
      if(err_state)
        return err_state; 
    
      struct addrinfo *res;
    
      int err = getaddrinfo(url, NULL, NULL, &res);
      
      printk("getaddrinfo err: %d\n\r", err);
      if(err)
        return STATUS_URL_ERROR;
    
      ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(port);
      struct sockaddr_in local_addr;
    
      local_addr.sin_family = AF_INET;
      local_addr.sin_port = htons(0);
      local_addr.sin_addr.s_addr = 0;
    
      *client_fd = socket(AF_INET, SOCK_STREAM, 0);
      printk("client_fd: %d\n\r", *client_fd);
    
      err = bind(*client_fd, (struct sockaddr *)&local_addr, sizeof(local_addr));
      
      if(err)
      {
        printk("bind err: %d\n\r", err);
        return STATUS_CONNECTION_ERROR;
        }
    	
      err = connect(*client_fd, (struct sockaddr *)res->ai_addr, sizeof(struct sockaddr_in));
      
      
      if(err < 0)
      {
        printk("connect err: %d\n\r", errno);
        return STATUS_CONNECTION_ERROR;
      }
      freeaddrinfo(res);
      printk("connected to server\n\r");
      return STATUS_NO_ERROR;
    }
    
    ERROR_STATUS blocking_send(int sock, u8_t *buf, u32_t datalen, u32_t flags, uint32_t timeout)
    {
       u32_t offset = 0U;
       volatile static int ret;
       s64_t  time_stamp = k_uptime_get();
       s64_t  milliseconds_spent = 0;
    
       while ((offset < datalen)&&(milliseconds_spent <timeout))
       {
          ret = send(sock, buf + offset,
                     MIN(4096, (datalen - offset)), flags);
          if (ret < 0)
          {
             return -errno;
          }
    
          offset += ret;
          milliseconds_spent += k_uptime_delta(&time_stamp);
       }
      if(milliseconds_spent >= timeout)
              return STATUS_TIMEOUT;
       return 0;
    }
    
    ERROR_STATUS blocking_recv(int fd, u8_t *buf, u32_t size, u32_t flags, uint32_t timeout)
    {
            volatile static int err;
            s64_t  time_stamp = k_uptime_get();
            s64_t  milliseconds_spent = 0;
    	do {
    		err = recv(fd, buf, size, flags);
    
                    k_sleep(10);                  
    
                    milliseconds_spent +=  k_uptime_delta(&time_stamp);
              } while ((err <= 0)&&(milliseconds_spent<timeout));
           
    
           if (err < 0)       
           {
              printk("recv socket err: %d, errno: %d\r\n", err, errno);
              return err;
            }
            if(milliseconds_spent >= timeout)
              return STATUS_TIMEOUT;
     
           return STATUS_NO_ERROR;
    }
    
    static void server_thread_fn(void *arg1, void *arg2, void *arg3)
    {
    	int client_fd;
        while(true)
            {          
                k_msgq_get(&xServerQueue, &task_com, K_FOREVER);
    		  
    			uint8_t* buffer = k_malloc(9000);
    			memset(buffer,0,9000);
    			server_connect(url,port,&client_fd);
    			blocking_send(client_fd,buffer,9000,0,60000);
    			blocking_recv(client_fd,buffer,9000,0,60000);
    			close(client_fd);
    			
    		}
    }

  • Thank you for the test code.

    I was able to reproduce this, and it seems to only manifest itself when filling up the buffer to 4k in bsdlib, where you have to try again until that packet has been free'd from the buffer. Changing the MIN to any number lower than 4096 bytes, for instance 4095 bytes, then it does not return EINPROGESS.

    I have reported this internally as a bug.

     

    Kind regards,

    Håkon

  • I think we just bumped into this issue but we're running on NCS v1.2 and BSDLIB 0.6.2 (slightly non-standard combination).  Was this bug fixed in any particular version of NCS or BSDLIB?

  • Hi,

     

    jbrzozoski said:
    I think we just bumped into this issue but we're running on NCS v1.2 and BSDLIB 0.6.2 (slightly non-standard combination).  Was this bug fixed in any particular version of NCS or BSDLIB?

    It was tested on ncs v1.3.0, which would mean bsdlib 0.7.3 was used. it was not reproducible at our end with this version. It is suspected that the rewrite in 0.7.0 (changelog here) fixed this issue.

     

    Kind regards,

    Håkon

Reply Children
No Data
Related