Re: cvs: php4 /ext/standard file.c

From: Date: Sat, 23 Dec 2000 19:49:52 +0000
Subject: Re: cvs: php4 /ext/standard file.c
References: 1 2  Groups: php.cvs 
Request: Send a blank email to php-cvs+get-3285@lists.php.net to get a copy of this message
Hi! >>>>> "Sascha" == Sascha Schumann <sascha@schumann.cx> writes: Sascha> Hi, >> The above is not really right; If you check the code of my_write(), >> it only uses errno if write() returns 0 or -1, in which case >> errno should contain the right error code. >> >> (I know that we do a check of ENOSCP for all cases, but as this error >> is not very likely and the only action we take is to sleep for a short >> time and then continue, this is not really fatal). Sascha> Right, that is the only case. The point here is that Sascha> my_write retries the write(), possibly generating SIGXFSZ. >> my_write() also does a retry until all bytes are written or until >> write() returns -1, so it's not likely that it should miss to write >> anything. >> >> Can you give us a scenario when my_write() can fail? Sascha> There are a couple of system calls which might set errno to Sascha> ENOSPC: Sascha> open() Sascha> link() Sascha> mkdir() Sascha> mkfifo() Sascha> rename() Sascha> write() Sascha> sem_init() Sascha> sem_open() Sascha> mq_open() Sascha> rf_create() Sascha> If such a system call fails and sets errno to ENOSPC and if Sascha> errno is not set afterwards, and if my_write() is invoked and Sascha> if there is less room than necessary to write the data to the Sascha> filesystem, SIGXFSZ will be delivered to the thread of Sascha> execution during the write() retry. MySQL doesn't catch the SIGXFSZ signal. In this case write() is supposed to return -1 and set errno accordingly. In other words, this should not be a problem. Sascha> Unless I'm missing something, there is no way to distinguish Sascha> these cases: First, the thread was interrupted by a signal Sascha> and some data was already written. A retry is perfectly Sascha> acceptable. Second, some data was written and the disk has Sascha> no more space. Retrying the write() causes SIGXFSZ. This Sascha> ambiguity is caused by write() not setting errno and simply Sascha> returning the number of bytes written. But this is not a problem with the current code(); If ENOSCP is set, then we only loose a sleep(), which is not perfect but will not crash anything (I already sent a mail with a single line fix to fix that). >> The only thing that 'may' conflict with the above in the my_write() >> code is that we check errno if write() returns 0. This isn't covered >> by your cases, but this is something I have seen happening with >> threads on some systems (in which case errno was always set to EINTR). Sascha> Do you remember on which systems that happened? I've walked Sascha> through the man pages of HPUX 10.20/11.0, FreeBSD 5.0, SunOS Sascha> 4.1.3/5.8, Ultrix 4.2, AIX 4.2, and OpenServer 5.0.6. The Sascha> only thing I could dig up were some references to returning Sascha> 0, if non-blocking I/O is used. The only irregularity I Sascha> found is on AIX which optionally returns -1 in the EINTR Sascha> case, although some data was already written. I am pretty sure that this happened on Solaris or SunOS; Even then it wasn't something that was documented but something that just happened! (Note that we also use my_write() for non-blocking IO, so we have to handle this case too) >> Anyway, I can't quickly see any scenario when my_write() would fail without >> having a correct my_errno/errno set. Sasha, if you could give us >> a scenario that proves me the current code wrong, then we will of >> course change it! Sascha> As I said before, this is a very unlikely case and applies to Sascha> regular files only. A quick grep through the MySQL sources Sascha> reveals that there is no apparent handling of SIGXFSZ, so it Sascha> is possible that, depending on the circumstances outlined Sascha> above, MySQL might get terminated during my_write (or are you Sascha> ignoring most signals by default?). We are ignoring most signals by default; We have often got a full disk with MySQL while testing and we know from practice that my_write() works perfectly even in this case The problem with signals and threads is that the standard is pretty broken regarding this; Many signals (like sigpipe) are delivered to 'any' thread, not the thread that had a problem; This makes it very hard to use signals and most threaded programs fixes this by having one thread that handles all signals and all other threads ignores most of the signals (MySQL works this way). Regards, Monty

« previous php.cvs (#3285) next »