czmq多个zactor实例崩溃

czmq多个zactor实例崩溃,c,pthreads,zeromq,C,Pthreads,Zeromq,我试图使用czmq库中的zhash和zactor编写一个基本示例。我努力实现的主要目标是: 创建1024个zactor实例,并在每个actor创建之后发送“START”命令 等待参与者的响应以继续创建zactors 删除以前创建的所有参与者 我有点不明白为什么这个代码会中断。每次我到达演员编号60时,应用程序就会退出: ... ... 58 actor started! START command received! 59 actor started! START command receive

我试图使用czmq库中的zhash和zactor编写一个基本示例。我努力实现的主要目标是:

  • 创建1024个zactor实例,并在每个actor创建之后发送“START”命令
  • 等待参与者的响应以继续创建zactors
  • 删除以前创建的所有参与者
  • 我有点不明白为什么这个代码会中断。每次我到达演员编号60时,应用程序就会退出:

    ...
    ...
    58 actor started!
    START command received!
    59 actor started!
    START command received!
    60 actor started!
    > Assertion failed: (self), function zsock_set_sndtimeo, file
    > src/zsock_option.c, line 1344.
    > Abort trap: 6
    
    编译:
    gcc-o demo.c-g-lczmq

    代码如下:

    #include <stdio.h>
    #include <czmq.h>
    
    typedef struct {
        zsock_t *pipe;              //  Actor command pipe
        zpoller_t *poller;          //  Socket poller
        int terminated;
    } accountactor_t;
    
    typedef struct{
        zactor_t *actor;
        int foo;
    } account_t;
    
    accountactor_t *
    accountactor_new (zsock_t *pipe, void *args)
    {
        accountactor_t *self = (accountactor_t *) zmalloc (sizeof (accountactor_t));
        assert (self);
    
        self->pipe = pipe;
        self->poller = zpoller_new (self->pipe, NULL);
            self->terminated = 0;
        return self;
    
    }
    
    static void
    accountactor_recv_api (accountactor_t *self)
    {
    //  Get the whole message of the pipe in one go
        zmsg_t *request = zmsg_recv (self->pipe);
        if (!request){
            return;        //  Interrupted
        }
    
        char *command = zmsg_popstr (request);
    
        if (streq (command, "START")){
                zsys_debug("START command received!");
            zsock_signal (self->pipe, 0);
        }else
        if (streq (command, "STOP")){
                zsys_debug("STOP command received!");
                zsock_signal (self->pipe, 0);
        }else
        if (streq (command, "$TERM")){
                zsys_debug("$TERM command received!");
            //  The $TERM command is send by zactor_destroy() method
            self->terminated = 1;
    
        }else {
            zsys_error ("Invalid command '%s'", command);
            zsock_signal (self->pipe, -1);
        }
    
        zmsg_destroy(&request);
        if(command){
            free(command);
        }
    }
    
    void
    actor_fcn (zsock_t *pipe, void *args)
    {
        accountactor_t * self = accountactor_new (pipe, args);
        if (!self)
            return;          //  Interrupted
    
            int rc  = 0;
        //  Signal actor successfully initiated
        zsock_signal (self->pipe, 0);
    
        while (!self->terminated) {
           zsock_t *which = (zsock_t *) zpoller_wait (self->poller, -1);
           if (which == self->pipe){
                            accountactor_recv_api (self);
           }
        }
    
            if(zpoller_terminated(self->poller)){
                zsys_debug("Poller Interrupted!");
            }else
            if(zpoller_expired(self->poller)){
                zsys_debug("Poller Expired!");
            }
    
            //  Free object itself
            zpoller_destroy (&self->poller);
            zsock_destroy(&self->pipe);
            free(self);
            self = NULL;
    
    }
    
    void
    s_account_free (void *argument)
    {
        account_t *account = (account_t *) argument;
            zstr_send (account->actor, "$TERM");
        zactor_destroy(&account->actor);
        free(account);
        zsys_debug("Item removed!");
    }
    
    int main(){
    
        zhash_t *table = zhash_new();
        int i = 0;
    
        account_t *ptrs[1024];
        char key[10];
    
        for(i=0; i<1024; i++){
    
            ptrs[i] = (account_t *) zmalloc (sizeof (account_t));
    
            ptrs[i]->actor = zactor_new (actor_fcn, NULL);
            sprintf(&key[0],"%d",i);
            zhash_insert(table, key, (void *)ptrs[i]);
            zhash_freefn(table, key, s_account_free);
    
            zstr_send (ptrs[i]->actor, "START");
            zsock_wait (ptrs[i]->actor);
            zsys_debug("%d actor started!",i);
    
        }
    
        i = zhash_size(table);
        // Delete all
        while(i--){
            sprintf(&key[0],"%d",i);
            zhash_delete(table, key);
            free(ptrs[i]);
        }
    
        return 0;
    
    }
    
    #包括
    #包括
    类型定义结构{
    zsock_t*pipe;//Actor命令管道
    zpoller\u t*poller;//套接字轮询器
    int终止;
    }会计人员;
    类型定义结构{
    zactor_t*演员;
    int foo;
    }账户;
    会计人员*
    accountactor_new(zsock_t*管道,void*参数)
    {
    accountactor_t*self=(accountactor_t*)zmaloc(sizeof(accountactor_t));
    断言(自我);
    自->管道=管道;
    self->poller=zpoller\u new(self->pipe,NULL);
    自->终止=0;
    回归自我;
    }
    静态空隙
    accountactor_recv_api(accountactor_t*self)
    {
    //一气呵成地获得管道的全部信息
    zmsg_t*请求=zmsg_recv(自->管道);
    如果(!请求){
    return;//中断
    }
    char*command=zmsg\u popstr(请求);
    if(streq(命令,“启动”)){
    zsys_调试(“收到启动命令!”);
    zsock_信号(自->管道,0);
    }否则
    if(streq(命令,“停止”)){
    zsys_调试(“收到停止命令!”);
    zsock_信号(自->管道,0);
    }否则
    if(streq(命令,“$TERM”)){
    zsys_debug(“$TERM命令已收到!”);
    //$TERM命令由zactor_destroy()方法发送
    自->终止=1;
    }否则{
    zsys_错误(“无效命令“%s”,命令);
    zsock_信号(自->管道,-1);
    }
    zmsg_销毁(和请求);
    如果(命令){
    自由(指挥);
    }
    }
    无效的
    参与者fcn(zsock_t*管道,无效*参数)
    {
    accountactor\u t*self=accountactor\u new(管道,参数);
    如果(!self)
    return;//中断
    int rc=0;
    //信号参与者已成功启动
    zsock_信号(自->管道,0);
    当(!self->终止){
    zsock_t*其中=(zsock_t*)zpoller_wait(self->poller,-1);
    if(which==self->pipe){
    accountactor_recv_api(自身);
    }
    }
    如果(zpoller_终止(self->poller)){
    zsys_调试(“轮询器中断!”);
    }否则
    如果(zpoller_过期(self->poller)){
    zsys_调试(“轮询器已过期!”);
    }
    //自由物体本身
    zpoller_销毁(&self->poller);
    zsock_销毁(&self->pipe);
    自由(自我);
    self=NULL;
    }
    无效的
    s_账户自由(无效*参数)
    {
    account_t*account=(account_t*)参数;
    zstr_发送(账户->参与者,“$TERM”);
    zactor_销毁(&account->actor);
    免费(账户);
    zsys_调试(“项目已删除!”);
    }
    int main(){
    zhash_t*表=zhash_new();
    int i=0;
    账户_t*ptr[1024];
    字符键[10];
    for(i=0;iactor=zactor\u new(actor\u fcn,NULL);
    sprintf(键[0],“%d”,i);
    zhash_插入(表,键,(空*)ptrs[i]);
    zhash_freefn(表、键、s_账户_free);
    zstr_send(ptrs[i]>actor,“START”);
    zsock_wait(ptrs[i]->actor);
    zsys_调试(“%d个参与者已启动!”,i);
    }
    i=zhash_尺寸(表);
    //全部删除
    而(我--){
    sprintf(键[0],“%d”,i);
    zhash_删除(表、键);
    免费(ptrs[i]);
    }
    返回0;
    }
    

    有什么想法吗?我不明白为什么我会达到60个数字的限制。

    你使用的是什么操作系统?是OS/X吗

    当前的actor实现仍然使用pairsocket,它们在内部使用实际的文件句柄来发送信号。每个actor有两个pairsocket,每个pairsocket使用两个文件句柄,因此60个actors=240个文件句柄

    在OS/X上,每个进程的默认限制为256。您可以提高此限制,请参阅:

    在Linux上,默认值是1024,您可以提高该值。在Windows上,您需要重新编译libzmq,并将FD_SETSIZE设置为16K或类似的值(这是libzmq master现在所做的,但旧版本的值较低)

    完全分开:

    • 您不需要在构造时进行任何握手,因为zactor_new()已经完成了这项工作,您将看到所有参与者在初始化后都会发送一个信号

    • 除非您实际测试系统限制,否则创建1024个参与者可能是多余的。参与者使用系统线程;为了获得最佳性能,您希望每个代码有一个线程。为了获得最佳设计,每个并发工作线程有一个线程


    是的,我使用的是OS/X,你是对的!我正在做的测试应用程序需要每个连接到服务器的客户端有一个工作线程,所以我测试这种方法,模拟如果1024个客户端连接,每个客户端都有各自的线程来处理自己的工作负载,会发生什么情况。我这样做是因为每个客户端都需要这是一个任务的连续执行,一旦客户端连接。感谢您指出这一点和反馈!