从多线程 RPC 服务器返回带有字符串的结构

Posted

技术标签:

【中文标题】从多线程 RPC 服务器返回带有字符串的结构【英文标题】:Return a struct with string from a multi threaded RPC server 【发布时间】:2017-07-23 19:14:39 【问题描述】:

我正在尝试编写一个返回结构的多线程 RPC 服务器。这是我的 XDR 文件。我正在运行rpcgen -MN foo.x 来生成多线程兼容代码。

// foo.x
struct foo_out 
  string name<128>;
;

program FOO_PROG 
  version FOO_VERS 
  foo_out foo(void) = 2;
   = 2 ;
 = 0x31230000;

这是我的服务器,您可以看到它需要一个指向我的结构的指针,为名称字符串分配一些内存,然后复制该字符串。我还添加了一个调试输出

// foo_server.c
#include "foo.h"
#include <stdio.h>
#include <stdlib.h>
#include <rpc/pmap_clnt.h>
#include <string.h>
#include <memory.h>
#include <sys/socket.h>
#include <netinet/in.h>

bool_t foo_2_svc(foo_out *out, struct svc_req *req) 
  out->name = malloc(sizeof("foo"));
  strcpy(out->name, "foo");
  printf("Value: '%s'\n", out->name);
  return TRUE;


int
foo_prog_2_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result) 
  xdr_free(xdr_result, result);
  return(1);

这是客户。它创建一个变量,传入一个指向该变量的指针,然后输出值:

// foo_client.c
#include "memory.h" /* for memset */
#include "foo.h"
#include "stdio.h"
#include "stdlib.h"
#include "rpc/pmap_clnt.h"
#include "string.h"
#include "memory.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include <unistd.h>

int
main (int argc,char **argv)

  CLIENT *cl;

  cl = clnt_create("127.0.0.1", FOO_PROG, FOO_VERS, "tcp");
  if (cl == NULL) 
    clnt_perror(cl, "call failed");
    exit (1);
  

  foo_out out;
  if (foo_2(&out, cl) != RPC_SUCCESS) 
    printf("failed \n");
    // exit(1);
  
  printf("foo out: %s\n",   out.name);

  sleep(1);
  exit(0);

当我运行它时,服务器很好,每次通过客户端调用它时我都会看到Value: 'foo'。但是,客户端因 segv 崩溃。使用地址清理程序我得到了这个:

=================================================================
==8269==ERROR: AddressSanitizer: SEGV on unknown address 0x0000004b0503 (pc 0x7fc9e2b5160f bp 0x000000000003 sp 0x7ffe264190c0 T0)
    #0 0x7fc9e2b5160e in xdr_string (/lib/x86_64-linux-gnu/libc.so.6+0x13b60e)
    #1 0x460751 in __interceptor_xdr_string.part.268 (/vagrant/foo/foo_client+0x460751)
    #2 0x4b04a7 in xdr_foo_out /vagrant/foo/foo_xdr.c:13
    #3 0x7fc9e2b4b3ea  (/lib/x86_64-linux-gnu/libc.so.6+0x1353ea)
    #4 0x4b03b8 in foo_2 /vagrant/foo/foo_clnt.c:15
    #5 0x4b042e in main /vagrant/foo/foo_client.c:28
    #6 0x7fc9e2a3682f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #7 0x405298 in _start (/vagrant/foo/foo_client+0x405298)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 xdr_string
==8269==ABORTING

当我使用 GDB 在foo_2 调用前后检查结构的内容时,它没有改变。看起来服务器根本没有修改值。

问题:如何使用多线程 RPC 调用修改带有字符串的结构?如果我将示例更改为使用整数而不是字符串,则可以正常工作。所以看起来我缺少一些基本的东西。关于我做错了什么或调试步骤的任何想法?

【问题讨论】:

Reddit 上有人发现了这个问题reddit.com/r/C_Programming/comments/6p8smu/… 【参考方案1】:

在您的客户端尝试为 foo_out 结构分配内存:

foo_out *out = malloc(sizeof(foo_out));
if (foo_2(out, cl) != RPC_SUCCESS) 
  printf("failed \n");
  // exit(1);

printf("foo out: %s\n",   out->name);

【讨论】:

仍然得到一个 segv,相同的位置,但现在我的记忆看起来像这样 $1 = name = 0xbebebebebebebebe &lt;error: Cannot access memory at address 0xbebebebebebebebe&gt; 啊,是的,看起来需要初始化名称。对不起,我没有帮助。 感谢您的评论。公平地说,我不确定为什么你的方法不起作用。我认为 malloc-ing 结构也会 malloc 指向char* 的指针。也许它因为其他原因失败了?

以上是关于从多线程 RPC 服务器返回带有字符串的结构的主要内容,如果未能解决你的问题,请参考以下文章

将带有第一个请求的 html 页面返回到在端口 5000 本地运行的 Json Rpc Dispatcher 服务器

PHP XML RPC - 如何处理返回的数组

RPC调用基础及Java学习笔记

RPC简单设计方案

在手动停止线程之前,JMeter 没有通过基于 TCP 协议的 JSON RPC 从服务器获得答案

从多对多关系返回一组随机排序的不同对象