質問

I have a weird problem with the posix socket api in vxworks 5.5.1. The code is trivial and probably not interesting (added below), but the gist of it is: When calling socket() and bind() in a separate function from the one calling recvfrom(), a pagefault occurs at the recvfrom() call. If everything is done in the same function it works fine. Note that the fault happens immediately when calling recvfrom(), not when a packet arrives.

Does VxWorks use the stack in some unexpected way for this API?

Edit: Added some code. The te_serve1() function works fine, but te_serve_one() (using helper functions) do not.

#include <taskLib.h>
#include <sysLib.h>
#include <string.h>
#include <taskLib.h>
#include <stdlib.h>
#include <stdio.h>
#include <types.h>
#include <sys/socket.h>
#include <sockLib.h>
#include <netinet/in.h>


#ifdef DEBUG
#define DP(...) printf(__VA_ARGS__)
#else
#define DP(...) do { } while(0)
#endif

#define LLB(l, b) ((l & (0x000000FF << (b*8))) >> b*8)


struct msg_log {
  unsigned long src;
  int           size;
};

static int setup(short port)
{
  int err = 0;
  struct sockaddr_in addr;
  int sock;

  DP("socket()\n");
  err = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (err < 0)
    return err;
  sock = err;

  addr.sin_family = AF_INET;
  addr.sin_port   = htons(7357);
  addr.sin_addr.s_addr = htonl(INADDR_ANY);

  DP("bind()\n");
  err = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
  if (err) {
    close(sock);
    return err;
  }

  return sock;
}

static int serve(int sock, struct msg_log *log)
{
  char buf[32];
  struct sockaddr_in caddr;
  int caddr_len = sizeof(caddr);
  int ret;
  int len;

  bzero((char *)&caddr, sizeof(caddr));
  DP("recvfrom()\n");
  ret = recvfrom(sock, buf, sizeof(buf), 0,
         (struct sockaddr *) &caddr, &caddr_len);
  if (ret < 0) return ret;
  len = ret;
  if (log) {
    DP("log()");
    log->src = caddr.sin_addr.s_addr;
    log->size = len;
  }
  DP("sendto()");
  ret = sendto(sock, (caddr_t) &buf, len, 0, (struct sockaddr *) &caddr, caddr_len);

  return ret;
}

static void serve_multiple(int sock)
{
  for (;;)
    if (serve(sock, NULL) < 0) break;
}

int te_serve_one(void)
{
  DP("%s\n", __FUNCTION__);
  int sock;
  struct msg_log log;  /* = {0}; */
  int ret = 0;
  short port = 1234;

  DP("setup()\n");
  sock = setup(port);
  if (sock < 0)
    goto out;
  sock = ret;
  ret = serve(sock, &log);
  if(ret < 0)
    goto tidy;

  DP("report:\n");
  printf("Echo'd %d byte to %lu.%lu.%lu.%lu\n",
     log.size,
     LLB(log.src, 0), 
     LLB(log.src, 1), 
     LLB(log.src, 2), 
     LLB(log.src, 3));

 tidy:
  DP("close()");
  close(sock);
 out:
  return ret;
}

int te_serve1(short port)
{
  int ret = 0;
  int sock;
  struct sockaddr_in addr;
  char buf[32];
  struct sockaddr_in caddr;
  int caddr_len = sizeof(caddr);
  int len;

  DP("socket()\n");
  ret = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (ret < 0)
    goto out;
  sock = ret;

  /* host addr */
  addr.sin_family = AF_INET;
  addr.sin_port   = htons(port);
  addr.sin_addr.s_addr = htonl(INADDR_ANY);

  DP("bind()\n");
  ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
  if (ret)
    goto tidy;

  /* serve */
  for (;;) {
    DP("recvfrom()\n");
    ret = recvfrom(sock, buf, sizeof(buf), 0,
           (struct sockaddr *) &caddr, &caddr_len);
    if (ret < 0)
      break;
    len = ret;

    if (len >= 4 && !strncmp(buf, "kill", 4)) {
      ret = 0;
      break;
    }

    DP("sendto()\n");
    ret = sendto(sock, (caddr_t) &buf, len, 0,
         (struct sockaddr *) &caddr, caddr_len);

    printf("Echo'd %d byte to %lu.%lu.%lu.%lu\n",
       len,
       LLB(caddr.sin_addr.s_addr, 0), LLB(caddr.sin_addr.s_addr, 1),
       LLB(caddr.sin_addr.s_addr, 2), LLB(caddr.sin_addr.s_addr, 3));
  }
 tidy:
  DP("close()");
  close(sock);
 out:
  return ret;
}
役に立ちましたか?

解決 2

Looking at the optimized assembly, I realized that the sock variable got overwritten by ret, which at that point is unused and initialized to zero. Splendid.

他のヒント

settup() declares following local:

struct sockaddr_in addr;

What happens if you declare "struct sockaddr_in addr;" in te_serve_one() and pass it to setup()?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top