V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
salamanderMH
V2EX  ›  问与答

C 语言_REENTRANT 这个宏

  •  
  •   salamanderMH · 2020-05-11 23:20:06 +08:00 · 1129 次点击
    这是一个创建于 1657 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题

    看了下这个库的源码,一个 FTP 的库,然后我看了下FtpConnect方法的实现,看到用到了_REENTRANT,不太清楚为什么要用这个宏,似乎是多线程有用

    GLOBALDEF int FtpConnect(const char *host, netbuf **nControl)
    {
        int sControl;
        struct sockaddr_in sin;
        int on=1;
        netbuf *ctrl;
        char *lhost;
        char *pnum;
    
        memset(&sin,0,sizeof(sin));
        sin.sin_family = AF_INET;
        lhost = strdup(host);
        pnum = strchr(lhost,':');
        if (pnum == NULL)
    	pnum = "ftp";
        else
    	*pnum++ = '\0';
        if (isdigit(*pnum))
    	sin.sin_port = htons(atoi(pnum));
        else
        {
    	struct servent *pse;
    #if _REENTRANT
    	struct servent se;
    	char tmpbuf[TMP_BUFSIZ];
    	int i;
    	if ( ( i = getservbyname_r(pnum,"tcp",&se,tmpbuf,TMP_BUFSIZ,&pse) ) != 0 )
    	{
    	    errno = i;
    	    if ( ftplib_debug )
    		perror("getservbyname_r");
    	    free(lhost);
    	    return 0;
    	}
    #else
    	if ((pse = getservbyname(pnum,"tcp") ) == NULL )
    	{
    	    if ( ftplib_debug )
    		perror("getservbyname");
    	    free(lhost);
    	    return 0;
    	}
    #endif
    	sin.sin_port = pse->s_port;
        }
        if ((sin.sin_addr.s_addr = inet_addr(lhost)) == INADDR_NONE)
        {
    	struct hostent *phe;
    #ifdef _REENTRANT
    	struct hostent he;
    	char tmpbuf[TMP_BUFSIZ];
    	int i, herr;
    	if ( ( ( i = gethostbyname_r( lhost, &he, tmpbuf, TMP_BUFSIZ, &phe, &herr ) ) != 0 ) ||
    	     ( phe == NULL ) )
    	{
    	    if ( ftplib_debug )
    		fprintf(stderr, "gethostbyname: %s\n", hstrerror(herr));
    	    free(lhost);
    	    return 0;
    	}
    #else
        	if ((phe = gethostbyname(lhost)) == NULL)
        	{
    	    if (ftplib_debug)
    		fprintf(stderr, "gethostbyname: %s\n", hstrerror(h_errno));
    	    free(lhost);
    	    return 0;
        	}
    #endif
        	memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length);
        }
        free(lhost);
        sControl = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (sControl == -1)
        {
    	if (ftplib_debug)
    	    perror("socket");
    	return 0;
        }
        if (setsockopt(sControl,SOL_SOCKET,SO_REUSEADDR,
    		   SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1)
        {
    	if (ftplib_debug)
    	    perror("setsockopt");
    	net_close(sControl);
    	return 0;
        }
        if (connect(sControl, (struct sockaddr *)&sin, sizeof(sin)) == -1)
        {
    	if (ftplib_debug)
    	    perror("connect");
    	net_close(sControl);
    	return 0;
        }
        ctrl = calloc(1,sizeof(netbuf));
        if (ctrl == NULL)
        {
    	if (ftplib_debug)
    	    perror("calloc");
    	net_close(sControl);
    	return 0;
        }
        ctrl->buf = malloc(FTPLIB_BUFSIZ);
        if (ctrl->buf == NULL)
        {
    	if (ftplib_debug)
    	    perror("calloc");
    	net_close(sControl);
    	free(ctrl);
    	return 0;
        }
        ctrl->handle = sControl;
        ctrl->dir = FTPLIB_CONTROL;
        ctrl->ctrl = NULL;
        ctrl->data = NULL;
        ctrl->cmode = FTPLIB_DEFMODE;
        ctrl->idlecb = NULL;
        ctrl->idletime.tv_sec = ctrl->idletime.tv_usec = 0;
        ctrl->idlearg = NULL;
        ctrl->xfered = 0;
        ctrl->xfered1 = 0;
        ctrl->cbbytes = 0;
        if (readresp('2', ctrl) == 0)
        {
    	net_close(sControl);
    	free(ctrl->buf);
    	free(ctrl);
    	return 0;
        }
        *nControl = ctrl;
        return 1;
    }
    
    4 条回复    2020-05-12 09:55:15 +08:00
    codehz
        1
    codehz  
       2020-05-11 23:30:44 +08:00 via Android
    只是用作特性开关吧,某个地方定义之后就用可重入的那块,不然就普通的
    shiny2017
        2
    shiny2017  
       2020-05-11 23:44:38 +08:00
    主要是区分比如: getservbyname_r 与 gethostbyname 之类的接口, 不带_r 后缀的就是不可重入的, 比如 gethostbyname 使用了全局变量或者静态变量, 如果进程的多个线程同时调用又不加锁的情况下, 都更新相同的全局变量会产生问题的.
    salamanderMH
        3
    salamanderMH  
    OP
       2020-05-12 09:53:05 +08:00
    @shiny2017 谢谢,那看起来`gethostbyname`和`getservbyname`有线程安全问题。
    salamanderMH
        4
    salamanderMH  
    OP
       2020-05-12 09:55:15 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2867 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 09:16 · PVG 17:16 · LAX 01:16 · JFK 04:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.