[Bug libgcj/29604] Race condition in ServerSocket.accept()
daney at gcc dot gnu dot org
gcc-bugzilla@gcc.gnu.org
Sat May 19 17:12:00 GMT 2007
------- Comment #5 from daney at gcc dot gnu dot org 2007-05-19 18:12 -------
UNIX/Linux sucks.
There are likely races with read/write and close all over libgcj:
=================================================================
Thread 1 Thread 2 Thread 3
load fd from memory (a field).
close fd
Open new fd with same #
read from fd
=================================================================
The main problem being that file descriptors are reused as soon as possible.
This makes multi-thread safe file operations very difficult.
One solution:
At libgcj initialization time do:
=====================================
int pe[2];
pipe(pe);
close(pe[0]);
int global_always_error_fd = pe[1];
=====================================
All Classes that use descriptors have:
======================
int fileDesInUse;
int fileDes;
int cleanupFD = -1;
======================
A read operation is like this:
===============================
synchronized {
fileDesInUse++;
}
// use the descriptor
read(fileDes, ....);
synchronized {
fileDesInUse--;
if (cleanupFD != -1 && fileDesInUse == 0) {
close(cleanupFD);
cleanupFD = -1;
}
}
========================
And close is like this:
========================
cleanupFD = dup(fileDes)
dup2(global_always_error_fd, fileDes);
synchronized {
if (fileDesInUse == 0) {
close(cleanupFD);
cleanupFD = -1;
}
}
========================
dup2 is an atomic operation that assures that the file descriptor can not be
reused by another thread while we might be using it.
The real close is done on a descriptor that is not in use by any other object.
The extra descriptors created with all the duping are closed when it is certian
that nothing is using them.
Yuck.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29604
More information about the Gcc-bugs
mailing list