goahead占用CPU问题

调试64位的rockchip.连接时占用大量CPU

定位到websServiceEvents(),其中socketSelect不停的退出。

/*
    Basic event loop. SocketReady returns true when a socket is ready for service. SocketSelect will block until an
    event occurs. SocketProcess will actually do the servicing.
 */
PUBLIC void websServiceEvents(int *finished)
{
    int     delay, nextEvent;

    if (finished) {
        *finished = 0;
    }
    delay = 0;
    while (!finished || !*finished) {
        if (socketSelect(-1, delay)) {
            socketProcess();
        }
#if ME_GOAHEAD_CGI
        delay = websCgiPoll();
#else
        delay = MAXINT;
#endif
        nextEvent = websRunEvents();
        delay = min(delay, nextEvent);
    }
}
才在网上搜到这篇博文。64位系统问题导致。

假设在32位arm平台的一个移位操作

int bit = 1<<30;

这是合法的。

那么平台换成了64位arm,

int bit = 1 << 34;

合法吗,显然不合法,因为int的长度就是32 比特,不管32位arm还是64位arm上。要移动34位显然超出了它的表示范围。

我们知道在aarch64架构下,long是64位的,那么改成:

long bit = 1 << 34 合法吗。并不。因为这里的1 其实是个int型,默认的嘛。长度仍然是32位!所以对一个32位的int型移位34 显然也不合法。

那么只有改成:

long bit = (long)1 << 34

才是正确的。

这个BUG始于这几天调试的goahead。平台是aarch64 海思。

一旦创建了很多VPSS,也就是创建了很多文件描述符,那么goahead监听的文件描述符就可能很大,goahead做select掩码的时候,不仅仅掩码类型是int,连特么移位的1 也是保持默认的int型。这样整个goahead服务已启动就会不停的select退出,这个服务沙雕。

贴出原有代码:

PUBLIC int socketSelect(int sid, int timeout)

{

WebsSocket *sp;

struct timeval tv;

fd_mask *readFds, *writeFds, *exceptFds;

int all, len, nwords, index, bit, nEvents;

/*

Allocate and zero the select masks

*/

nwords = (socketHighestFd + NFDBITS) / NFDBITS;

len = nwords * sizeof(fd_mask);

readFds = walloc(len);

memset(readFds, 0, len);

writeFds = walloc(len);

memset(writeFds, 0, len);

exceptFds = walloc(len);

memset(exceptFds, 0, len);

tv.tv_sec = timeout / 1000;

tv.tv_usec = (timeout % 1000) * 1000;

/*

Set the select event masks for events to watch

*/

all = nEvents = 0;

if (sid < 0) {

all++;

sid = 0;

}

for (; sid < socketMax; sid++) {

if ((sp = socketList[sid]) == NULL) {

if (all == 0) {

break;

} else {

continue;

}

}

assert(sp);

/*

Initialize the ready masks and compute the mask offsets.

*/

index = sp->sock / (NBBY * sizeof(fd_mask));

bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));

if (sp->handlerMask & SOCKET_READABLE) {

readFds[index] |= bit;

}

if (sp->handlerMask & SOCKET_WRITABLE) {

writeFds[index] |= bit;

}

if (sp->handlerMask & SOCKET_EXCEPTION) {

exceptFds[index] |= bit;

}

if (sp->flags & SOCKET_RESERVICE) {

tv.tv_sec = 0;

tv.tv_usec = 0;

}

.................................

注意看加粗部分。bit用于计算掩码位,index用于计算字节数。aarch64上NBBY 和

sizeof(fd_mask)都是8.可见这里bit计算必定会出篓子,自己是int型,用于移位的1也是默认的int.

那么如何修改呢?简单,把bit设为long, 1 也强制转换成long 就行了。:

long all, len, nwords, index, bit, nEvents;

....

index = sp->sock / (NBBY * sizeof(fd_mask));

bit = (long)1 << (sp->sock % (NBBY * sizeof(fd_mask)));

这样就解决了。
 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值