Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 14 May 2005 23:01:30 -0400
From:      Craig Rodrigues <rodrigc@crodrigues.org>
To:        Xin LI <delphij@freebsd.org>
Cc:        cvs-all@freebsd.org
Subject:   Re: cvs commit: src/lib/libc/gen ttyname.c
Message-ID:  <20050515030130.GA63641@crodrigues.org>
In-Reply-To: <200505141403.j4EE3LYX097762@repoman.freebsd.org>
References:  <200505141403.j4EE3LYX097762@repoman.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--3MwIy2ne0vdjdPXF
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Sat, May 14, 2005 at 02:03:21PM +0000, Xin LI wrote:
> delphij     2005-05-14 14:03:21 UTC
> 
>   FreeBSD src repository
> 
>   Modified files:
>     lib/libc/gen         ttyname.c 
>   Log:
>   Revert to old ttyname_r behavior that when _ioctl() returns 0 (SUCCEEDED),
>   return the buffer immediately.  This will permit ssh and/or PAM logins
>   broken by previous commit.
>   
>   The (potential) underlying problem is still under investigation.
>   
>   Point hat to:   me

Thanks for committing this.  To some extent, I think I deserve
a pointy hat too, because my original patch included the "return (EINVAL);"
which you had to change to "return 0;" to solve the problem with ssh.

I would like to ask a question.
I believe that the original code in our ttyname() which
attempts to make it thread-safe if linked with -pthread is
kind of bogus.

If you link code with -pthread (and __isthreaded=1), then
in ttyname() in /usr/src/lib/libc/gen/ttyname.c, there
is a malloc() called, but there is no corresponding free().
malloc() is never called if __isthreaded=0.

This is totally bogus, because ttyname() is not documented
to require the caller to call free() on any buffer.  So
we are introducing a potential memory leak,
because ttyname() does not do a malloc if __isthreaded=0,
but it does a malloc() without a corresponding free if __isthreaded=1. 

My opinion is that ttyname() should behave the same way
with respect to memory allocation if linked with -pthread or not.

ttyname() was never a thread-safe interface, and previous
attempts to make it so were well-intentioned, but in my opinion, wrong.

Now that we have a standards-compliant ttyname_r() in the tree
which is thread-safe, I propose the attached patch.

I did not submit this patch originally, because I thought it would
be too much, and prevent a standards-compliant ttyname_r() from
going in the tree.  Now that we have a standards-compliant
ttyname_r() in the tree, I'd like to see this potential memory
leak in ttyname() plugged.  The behavior is non-standard, if linked with
-pthread.......these kinds of things are so annoying
when you are trying to track down memory leaks.

What do you think?

-- 
Craig Rodrigues        
rodrigc@crodrigues.org

--3MwIy2ne0vdjdPXF
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="patch1.txt"

Index: ttyname.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/gen/ttyname.c,v
retrieving revision 1.19
diff -u -r1.19 ttyname.c
--- ttyname.c	14 May 2005 14:03:21 -0000	1.19
+++ ttyname.c	15 May 2005 02:53:04 -0000
@@ -57,10 +57,6 @@
 
 static char ttyname_buf[sizeof(_PATH_DEV) + MAXNAMLEN];
 
-static pthread_mutex_t	ttyname_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_key_t	ttyname_key;
-static int		ttyname_init = 0;
-
 int
 ttyname_r(int fd, char *buf, size_t len)
 {
@@ -92,39 +88,10 @@
 char *
 ttyname(int fd)
 {
-	char	*buf;
+	if (ttyname_r(fd, ttyname_buf, sizeof ttyname_buf) != 0)
+		return (NULL);
+	else
+		return (ttyname_buf);
 
-	if (__isthreaded == 0) {
-		if (ttyname_r(fd, ttyname_buf, sizeof ttyname_buf) != 0)
-			return (NULL);
-		else
-			return (ttyname_buf);
-	}
-
-	if (ttyname_init == 0) {
-		_pthread_mutex_lock(&ttyname_lock);
-		if (ttyname_init == 0) {
-			if (_pthread_key_create(&ttyname_key, free)) {
-				_pthread_mutex_unlock(&ttyname_lock);
-				return (NULL);
-			}
-			ttyname_init = 1;
-		}
-		_pthread_mutex_unlock(&ttyname_lock);
-	}
-
-	/* Must have thread specific data field to put data */
-	if ((buf = _pthread_getspecific(ttyname_key)) == NULL) {
-		if ((buf = malloc(sizeof(_PATH_DEV) + MAXNAMLEN)) != NULL) {
-			if (_pthread_setspecific(ttyname_key, buf) != 0) {
-				free(buf);
-				return (NULL);
-			}
-		} else {
-			return (NULL);
-		}
-	}
-	ttyname_r(fd, buf, sizeof(_PATH_DEV) + MAXNAMLEN);
-	return (buf);
 }
 

--3MwIy2ne0vdjdPXF--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050515030130.GA63641>