【问题标题】:GWAN terminating under loadGWAN 在负载下终止
【发布时间】:2013-07-08 18:08:56
【问题描述】:

我有一个 web 应用程序,它需要一个安静的界面。所以我有一个连接处理程序,它试图将入站请求更改为 gwan 可以使用的东西。

到此服务的每个连接都是相同的,所以我对每个连接都进行了替换:

  #include "gwan.h" // G-WAN exported functions

  #include <stdio.h>
  int init(int argc, char *argv[]){
     u32 *states = (u32*)get_env(argv, US_HANDLER_STATES);
     *states = 1 << HDL_AFTER_READ; // we assume "GET /hello" sent in one shot
     return 0;
  }

  void clean(int argc, char *argv[]){}

  int main(int argc, char *argv[])
  {
     const long state = (long)argv[0];
     if(state == HDL_AFTER_READ) {
        xbuf_t *read_xbuf = (xbuf_t*)get_env(argv, READ_XBUF);
        xbuf_replfrto(read_xbuf, read_xbuf->ptr, read_xbuf->ptr + 16, "/classify.htm?", "/?boost.cpp&");
     }

     return 255;
  }

问题是,在负载下,过了一会儿,G-WAN 崩溃并给我一个错误:

G-WAN 4.3.14 (pid:20477)

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_S_construct NULL not valid


Signal        : 6:Abort
Signal src    : -6:tkill
errno         : 0
Thread        : 2
Code   Pointer: 7fc5dcd748a5 (module:libc.so.6, function:raise, line:0)
Access Address: 000000004ffd

Registers     : EAX=000000000000 CS=00000033 EIP=7fc5dcd748a5 EFLGS=000000000202
                EBX=0000006693e8 SS=0000000a ESP=7fc5d5c7bf38 EBP=7fc5880008d8
                ECX=ffffffffffffffff DS=0000000a ESI=00000000504e FS=00000033
                EDX=000000000006 ES=0000000a EDI=000000004ffd CS=00000033

Module         :Function        :Line # PgrmCntr(EIP)  RetAddress  FramePtr(EBP)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Aborted (core dumped)

只有当我让服务器处于负载状态时才会出现问题。在一台机器上,我每秒处理大约 8000 个请求,并且在崩溃前持续了大约 5 秒。

如果我不进行重写(将 main.c 移动到 main.c_)并直接调用 cpp 脚本,则不会崩溃...

帮助!有什么想法吗?

谢谢

【问题讨论】:

  • 我建议您进行 "in-place" 重写,对源和目标使用相同的长度。这将使事情变得比玩内存重新分配更快、更可靠(“中止”由 GLIBC 完成,不由信号处理程序处理)。

标签: g-wan


【解决方案1】:

它位于代码的不同部分...最大的线索是它看起来像我遇到了一个 C++ 未处理的异常。

根据文档,G-Wan 是用 C 编写的。

挖掘我的代码,并在我怀疑代码崩溃的地方添加了一些异常处理,我看到了异常,但服务器继续运行,这正是我想要的!

我修复它的片段:

try {
  get_arg("key=",&name,argc,argv);
  string url = name;

  boost::thread cls(classify_url,url,boost::ref(rp));
  if(!cls.timed_join(boost::posix_time::milliseconds(8))) {
   cls.interrupt();
   rp="{\"c\": [998]}";
  }
}
catch(...) {
   rp="{\"c\": [997]}";
   cout << "EXCEPTION" << endl;
}

添加了 try/catch,一切都很好!

【讨论】:

  • 我建议您进行 "in-place" 重写,对源和目标使用相同的长度。这将使事情变得比玩内存重新分配更快、更可靠(“中止”由 GLIBC 完成,不由信号处理程序处理)。
【解决方案2】:

添加适当的返回值检查,不要认为任何事情都是理所当然的。

这看起来像 get_env 失败并返回 NULL,但你有很多事情要做(gdb、strace 等),所以有人可以帮助你。

【讨论】:

  • 这里最大的问题是g-wan服务器本身没有来源......做一个gdb bt,它没有提供任何有用的东西。最重要的是,它们对调试器有一些保护。使用 gdb 或 strace 运行时会出现 SegFaults ......
  • 啊,好吧,以前没来过关,很抱歉。除了告诉你检查get_env的返回值之外,真的帮不了你
  • 刚刚试过了,谢谢!将 xbuf_replfrto 包装在 if(read_xbuf!=NULL)....同样的结果...
  • 发现它在代码的不同部分......但同样的事情,一个例外。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-04
  • 2016-06-04
  • 2020-06-28
相关资源
最近更新 更多