| Anonymous | Login | Signup for a new account | 2013-05-19 12:53 CEST | ![]() |
| Main | My View | View Issues | Change Log | Roadmap |
| View Issue Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||||||
| ID | Project | Category | View Status | Date Submitted | Last Update | ||||||
| 0003784 | OCaml | OCaml general | public | 2005-09-07 04:55 | 2009-05-19 18:15 | ||||||
| Reporter | administrator | ||||||||||
| Assigned To | |||||||||||
| Priority | normal | Severity | feature | Reproducibility | always | ||||||
| Status | acknowledged | Resolution | open | ||||||||
| Platform | OS | OS Version | |||||||||
| Product Version | |||||||||||
| Target Version | Fixed in Version | ||||||||||
| Summary | 0003784: Racy libc calls | ||||||||||
| Description | Full_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)); | ||||||||||
| Tags | No tags attached. | ||||||||||
| Attached Files | |||||||||||
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 |