Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0003784OCamlOCaml generalpublic2005-09-07 04:552009-05-19 18:15
Reporteradministrator 
Assigned To 
PrioritynormalSeverityfeatureReproducibilityalways
StatusacknowledgedResolutionopen 
PlatformOSOS Version
Product Version 
Target VersionFixed in Version 
Summary0003784: Racy libc calls
DescriptionFull_Name: Yaron Minsky
Version: 3.08.4
OS: Linux
Submission from: user-0cdfhf3.cable.mindspring.com (24.215.197.227)


It looks like OCaml makes a bunch of race-y calls to glibc functions.
The following is a quick list of places where suspicious function
calls appear. Most if not all of these calls are unproblematic when
only caml threads are involved, due to the locking of the main thread.
 But in cases where C threads are making calls to these functions
races can and will occur.

This list was compiled by going through the list of non-reentrant
functions given in Advanced Programming in the Unix environment, by
Stevens and Rago. Each of the included functions has an *_r version
that is reentrant, and should it appears be used instead. Some
functions that don't have alternatives (for example, dlload and
dbm_close) were not flagged.

We would be happy to submit a patch with these fixes to mainline, if
Inria is interested in some outside help.

## getlogin
./otherlibs/u (BUG)nix/getlogin.c:/* $Id: getlogin.c,v 1.8.6.1
2005/01/17 18:10:36 doligez Exp $ */
./otherlibs/unix/getlogin.c:extern char * getlogin(void);
./otherlibs/unix/getlogin.c:CAMLprim value unix_getlogin(value unit)
./otherlibs/unix/getlogin.c: name = getlogin();
./otherlibs/unix/getlogin.c: if (name == NULL) unix_error(ENOENT,
"getlogin", Nothing);
## gmtime
./otherlibs/unix/gmtime.c:/* $Id: gmtime.c,v 1.16.6.1 2004/08/23
11:31:44 doligez Exp $ */
./otherlibs/unix/gmtime.c:CAMLprim value unix_gmtime(value t)
./otherlibs/unix/gmtime.c: tm = gmtime(&clock);
./otherlibs/unix/gmtime.c: if (tm == NULL) unix_error(EINVAL,
"gmtime", Nothing);
## ctime
./otherlibs/win32unix/stat.c: value atime = Val_unit, mtime =
Val_unit, ctime = Val_unit;
./otherlibs/win32unix/stat.c: Begin_roots3(atime,mtime,ctime)
./otherlibs/win32unix/stat.c: ctime = copy_double((double) buf->st_ctime);
./otherlibs/win32unix/stat.c: Field (v, 11) = ctime;
./otherlibs/unix/utimes.c: times.actime = Double_val(atime);
./otherlibs/unix/utimes.c: if (times.actime || times.modtime)
./otherlibs/unix/stat.c: CAMLlocal5(atime, mtime, ctime, offset, v);
./otherlibs/unix/stat.c: ctime = copy_double((double) buf->st_ctime);
./otherlibs/unix/stat.c: Field (v, 11) = ctime;
## getprotobyname
./otherlibs/unix/getproto.c:CAMLprim value unix_getprotobyname(value name)
./otherlibs/unix/getproto.c: entry = getprotobyname(String_val(name));
./otherlibs/unix/getproto.c:CAMLprim value unix_getprotobyname(value name)
./otherlibs/unix/getproto.c:{ invalid_argument("getprotobyname not
implemented"); }
## getprotobynumber
./otherlibs/unix/getproto.c:CAMLprim value unix_getprotobynumber(value proto)
./otherlibs/unix/getproto.c: entry = getprotobynumber(Int_val(proto));
./otherlibs/unix/getproto.c:CAMLprim value unix_getprotobynumber(value proto)
./otherlibs/unix/getproto.c:{ invalid_argument("getprotobynumber not
implemented"); }
## getpwnam
./otherlibs/unix/getpw.c:CAMLprim value unix_getpwnam(value name)
./otherlibs/unix/getpw.c: entry = getpwnam(String_val(name));
## getpwuid
./otherlibs/unix/getpw.c:CAMLprim value unix_getpwuid(value uid)
./otherlibs/unix/getpw.c: entry = getpwuid(Int_val(uid));
## localtime
./otherlibs/unix/gmtime.c:CAMLprim value unix_localtime(value t)
./otherlibs/unix/gmtime.c: tm = localtime(&clock);
./otherlibs/unix/gmtime.c: if (tm == NULL) unix_error(EINVAL,
"localtime", Nothing);
## strerror
./byterun/sys.c: return strerror(errno);
./otherlibs/win32unix/errmsg.c: return copy_string(strerror(errnum));
./otherlibs/systhreads/posix.c: err = strerror(retcode);
./otherlibs/unix/errmsg.c: return copy_string(strerror(errnum));
## getservbyname
./otherlibs/unix/getserv.c:CAMLprim value unix_getservbyname(value
name, value proto)
./otherlibs/unix/getserv.c: entry = getservbyname(String_val(name),
String_val(proto));
./otherlibs/unix/getserv.c:CAMLprim value unix_getservbyname(value
name, value proto)
./otherlibs/unix/getserv.c:{ invalid_argument("getservbyname not
implemented"); }
## getgrgid
./otherlibs/unix/getgr.c:CAMLprim value unix_getgrgid(value gid)
./otherlibs/unix/getgr.c: entry = getgrgid(Int_val(gid));
## getservbyport
./otherlibs/unix/getserv.c:CAMLprim value unix_getservbyport(value
port, value proto)
./otherlibs/unix/getserv.c: entry =
getservbyport(htons(Int_val(port)), String_val(proto));
./otherlibs/unix/getserv.c:CAMLprim value unix_getservbyport(value
port, value proto)
./otherlibs/unix/getserv.c:{ invalid_argument("getservbyport not
implemented"); }
## getgrnam
./otherlibs/unix/getgr.c:CAMLprim value unix_getgrnam(value name)
./otherlibs/unix/getgr.c: entry = getgrnam(String_val(name));

  ReplyForward
        
        
Mail Delivery System
<MAILER-DAEMON@brion.inria.fr> to me
     More options 10:53 pm (1 minute ago)
This is the Postfix program at host brion.inria.fr.

I'm sorry to have to inform you that your message could not be
be delivered to one or more recipients. It's attached below.

For further assistance, please send mail to <postmaster>

If you do so, please include this problem report. You can
delete your own text from the attached returned message.

                       The Postfix program

<caml-bugs@brion.inria.fr> (expanded from <caml-bugs@caml.inria.fr>): unknown
   user: "caml-bugs"


Final-Recipient: rfc822; caml-bugs@brion.inria.fr
Original-Recipient: rfc822; caml-bugs@caml.inria.fr
Action: failed
Status: 5.0.0
Diagnostic-Code: X-Postfix; unknown user: "caml-bugs"



---------- Forwarded message ----------
From: Yaron Minsky <yminsky@gmail.com>
To: caml-bugs@caml.inria.fr
Date: Tue, 6 Sep 2005 22:53:10 -0400
Subject: Use of racy libc calls
It looks like OCaml makes a bunch of race-y calls to glibc functions.
The following is a quick list of places where suspicious function
calls appear. Most if not all of these calls are unproblematic when
only caml threads are involved, due to the locking of the main thread.
 But in cases where C threads are making calls to these functions
races can and will occur.

This list was compiled by going through the list of non-reentrant
functions given in Advanced Programming in the Unix environment, by
Stevens and Rago. Each of the included functions has an *_r version
that is reentrant, and should it appears be used instead. Some
functions that don't have alternatives (for example, dlload and
dbm_close) were not flagged.

We would be happy to submit a patch with these fixes to mainline, if
Inria is interested in some outside help.

## getlogin
./otherlibs/u (BUG)nix/getlogin.c:/* $Id: getlogin.c,v 1.8.6.1
2005/01/17 18:10:36 doligez Exp $ */
./otherlibs/unix/getlogin.c:extern char * getlogin(void);
./otherlibs/unix/getlogin.c:CAMLprim value unix_getlogin(value unit)
./otherlibs/unix/getlogin.c: name = getlogin();
./otherlibs/unix/getlogin.c: if (name == NULL) unix_error(ENOENT,
"getlogin", Nothing);
## gmtime
./otherlibs/unix/gmtime.c:/* $Id: gmtime.c,v 1.16.6.1 2004/08/23
11:31:44 doligez Exp $ */
./otherlibs/unix/gmtime.c:CAMLprim value unix_gmtime(value t)
./otherlibs/unix/gmtime.c: tm = gmtime(&clock);
./otherlibs/unix/gmtime.c: if (tm == NULL) unix_error(EINVAL,
"gmtime", Nothing);
## ctime
./otherlibs/win32unix/stat.c: value atime = Val_unit, mtime =
Val_unit, ctime = Val_unit;
./otherlibs/win32unix/stat.c: Begin_roots3(atime,mtime,ctime)
./otherlibs/win32unix/stat.c: ctime = copy_double((double) buf->st_ctime);
./otherlibs/win32unix/stat.c: Field (v, 11) = ctime;
./otherlibs/unix/utimes.c: times.actime = Double_val(atime);
./otherlibs/unix/utimes.c: if (times.actime || times.modtime)
./otherlibs/unix/stat.c: CAMLlocal5(atime, mtime, ctime, offset, v);
./otherlibs/unix/stat.c: ctime = copy_double((double) buf->st_ctime);
./otherlibs/unix/stat.c: Field (v, 11) = ctime;
## getprotobyname
./otherlibs/unix/getproto.c:CAMLprim value unix_getprotobyname(value name)
./otherlibs/unix/getproto.c: entry = getprotobyname(String_val(name));
./otherlibs/unix/getproto.c:CAMLprim value unix_getprotobyname(value name)
./otherlibs/unix/getproto.c:{ invalid_argument("getprotobyname not
implemented"); }
## getprotobynumber
./otherlibs/unix/getproto.c:CAMLprim value unix_getprotobynumber(value proto)
./otherlibs/unix/getproto.c: entry = getprotobynumber(Int_val(proto));
./otherlibs/unix/getproto.c:CAMLprim value unix_getprotobynumber(value proto)
./otherlibs/unix/getproto.c:{ invalid_argument("getprotobynumber not
implemented"); }
## getpwnam
./otherlibs/unix/getpw.c:CAMLprim value unix_getpwnam(value name)
./otherlibs/unix/getpw.c: entry = getpwnam(String_val(name));
## getpwuid
./otherlibs/unix/getpw.c:CAMLprim value unix_getpwuid(value uid)
./otherlibs/unix/getpw.c: entry = getpwuid(Int_val(uid));
## localtime
./otherlibs/unix/gmtime.c:CAMLprim value unix_localtime(value t)
./otherlibs/unix/gmtime.c: tm = localtime(&clock);
./otherlibs/unix/gmtime.c: if (tm == NULL) unix_error(EINVAL,
"localtime", Nothing);
## strerror
./byterun/sys.c: return strerror(errno);
./otherlibs/win32unix/errmsg.c: return copy_string(strerror(errnum));
./otherlibs/systhreads/posix.c: err = strerror(retcode);
./otherlibs/unix/errmsg.c: return copy_string(strerror(errnum));
## getservbyname
./otherlibs/unix/getserv.c:CAMLprim value unix_getservbyname(value
name, value proto)
./otherlibs/unix/getserv.c: entry = getservbyname(String_val(name),
String_val(proto));
./otherlibs/unix/getserv.c:CAMLprim value unix_getservbyname(value
name, value proto)
./otherlibs/unix/getserv.c:{ invalid_argument("getservbyname not
implemented"); }
## getgrgid
./otherlibs/unix/getgr.c:CAMLprim value unix_getgrgid(value gid)
./otherlibs/unix/getgr.c: entry = getgrgid(Int_val(gid));
## getservbyport
./otherlibs/unix/getserv.c:CAMLprim value unix_getservbyport(value
port, value proto)
./otherlibs/unix/getserv.c: entry =
getservbyport(htons(Int_val(port)), String_val(proto));
./otherlibs/unix/getserv.c:CAMLprim value unix_getservbyport(value
port, value proto)
./otherlibs/unix/getserv.c:{ invalid_argument("getservbyport not
implemented"); }
## getgrnam
./otherlibs/unix/getgr.c:CAMLprim value unix_getgrnam(value name)
./otherlibs/unix/getgr.c: entry = getgrnam(String_val(name));

TagsNo tags attached.
Attached Files

- Relationships

-  Notes
(0000275)
administrator (administrator)
2005-10-12 15:02

The reentrant _r alternate libc functions are not always available ->
configuration problem. Keep this as feature wish.
(0003388)
anonymous (viewer)
2005-11-24 11:43

I believe many C libraries automatically use thread-local storage for (all? most of?) these functions. This is certainly the case for GNU libc.
(0004960)
shinwell (developer)
2009-05-19 18:15

I've come across this issue again recently - just a reminder :) The configure script could check for the presence of the _r functions. I'm not sure whether there is a definitive reference for which of these might use TLS, but again, that will be very C library dependent.

- Issue History
Date Modified Username Field Change
2005-11-18 10:13 administrator New Issue
2005-11-24 11:43 anonymous Note Added: 0003388
2009-05-19 18:15 shinwell Note Added: 0004960


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker