php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #35894 php-imap doesn't trap USR2 when mailbox is locked
Submitted: 2006-01-04 15:40 UTC Modified: 2010-12-01 16:17 UTC
Votes:5
Avg. Score:3.4 ± 0.8
Reproduced:2 of 3 (66.7%)
Same Version:2 (100.0%)
Same OS:1 (50.0%)
From: jik at kamens dot brookline dot ma dot us Assigned:
Status: Analyzed Package: IMAP related
PHP Version: 5.1.2 OS: Linux
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2006-01-04 15:40 UTC] jik at kamens dot brookline dot ma dot us
Description:
------------
The imap c-client has code in it to send a "kiss of death" SIGUSR2 to another process that has a mailbox locked, to cause that process to give up the lock if it no longer needs it.  Anything which uses c-client is supposed to define a singla handler for SIGUSR2 to catch the signal and at minimum ignore it if the client doesn't want to relinquish the lock.  If it doesn't do this, then the SIGUSR2 causes the process to die, and then the other process, which sent the signal, claims the lock.

It appears that PHP's imap support doesn't define a SIGUSR2 handler, which means that if (a) imap_open is used to open a local file and (b) another process on the same machine happens to use c-client to open the same file at around the same time, the first process will die silently because of the SIGUSR2.

To fix this, imap_open needs to define a SIGUSR2 handler to catch and ignore the signal while it's got the mailbox locked.

Reproduce code:
---------------
Put this script in a file and run it with one argument, the name of a non-empty local mailbox, twice at the same time, e.g. (from bash) "php /tmp/imap_open.php /var/mail/jik & php /tmp/imap_open.php /var/mail/jik".  It may not fail every time, but at least some of the times you do this, okne of the two php processes will print an error and exit because of the USR2 signal.



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-01-04 15:48 UTC] jik at kamens dot brookline dot ma dot us
Woops, forgot the script.  Here it is:

<?php

imap_open($argv[1], "", "");

?>

You probably could have figured this out :-).  You need an mbox file on which to run imap_open; there's no way to eliminate that dependency.
 [2006-01-04 19:33 UTC] tony2001@php.net
Can't reproduce.
I don't see any error messages and the script works fine.
 [2006-01-04 19:51 UTC] jik at kamens dot brookline dot ma dot us
$ ls -l /var/mail/jik; php /tmp/imap_open.php /var/mail/jik & php /tmp/imap_open.php /var/mail/jik
-rw------- 1 jik mail 871 Jan  4 13:44 /var/mail/jik
[1] 31702
starting to open mailbox
starting to open mailbox
successfully opened mailbox
PHP Notice:  Unknown: Trying to get mailbox lock from process 31702 (errflg=1) in Unknown on line 0
[1]+  User defined signal 2   php /tmp/imap_open.php /var/mail/jik
$ 

New version of the script:

<?php
print "starting to open mailbox\n";
imap_open($argv[1], "", "");
print "successfully opened mailbox\n";
?>

I don't know why you can't reproduce it; it reproduces easily for me, as shown above.  The c-client documentation and source code make it clear that this is going on, so unless you can confirm that PHP is installing a USR2 handle when locking mailboxes, I'm pretty sure it's a problem.
 [2006-01-04 19:52 UTC] jik at kamens dot brookline dot ma dot us
Did you run the script twice at the same time as I said in my report?  That's the only way you're going to be able to reproduce it, since it requires contention from two different processes.
 [2006-01-04 19:53 UTC] jik at kamens dot brookline dot ma dot us
Also, let me remind you that it won't happen if the mailbox file is empty; it needs to have messages in it, or c-client won't lock it.
 [2006-01-04 19:59 UTC] tony2001@php.net
>Did you run the script twice at the same time as I said in my report? 
Yes. And the mailbox is not empty.
 [2006-01-04 21:14 UTC] jik at kamens dot brookline dot ma dot us
There's a patch which makes this problem go away at http://stuff.mit.edu/~jik/php-5.1.1-imap-usr2.patch.txt.  However, rather than using the #if statement I used to figure out whether to enable the relevant code, you may want to insert a check for the function arm_signal in the c-client library in the configure script, define a cpp symbol if the function exists, and use my code if that cpp symbol is defined.
 [2006-01-04 21:49 UTC] sniper@php.net
Exactly what c-client version you linked PHP with?
And how was it compiled?
 [2006-01-04 21:53 UTC] jik at kamens dot brookline dot ma dot us
libc-client-2002e-18.1 RPM from Fedora Core.  I checked the current c-client sources from washington.edu and they seem susceptible to this problem as well, judging from an examination of the source code.  The USR2 functionality has been in c-client since 1993, as far as I can tell.
 [2006-01-05 01:01 UTC] sniper@php.net
I get the same notices, which seem quite harmless anyway. And your patch did not make any difference whatsoever.

 [2006-01-05 04:13 UTC] jik at kamens dot brookline dot ma dot us
Please look carefully at the output.  The notices are not "harmless".  Note that the message "successfully opened mailbox" only appears *once*.  It should appear twice, because there are two processes who both want to open the mailbox.  It only appears once because one of the two processes is killed by a USR2 signal as I've described.

I don't know why the patch I sent didn't help for you.  It reliably solves the problem for me.  Perhaps I picked bad preprocessor symbols and it's not actually getting compiled into the object code on your system.  Can you put debugging code in to see if the arm_signal calls are actually happening?

Thanks.
 [2006-01-05 10:07 UTC] sniper@php.net
Why would you want to allow opening same mailbox by two simultaneous processes?
 [2006-01-05 15:56 UTC] jik at kamens dot brookline dot ma dot us
You *don't* want to allow the simultaneous opening of a mailbox by two processes.  The whole point of locking is to *prevent* the simultaneous opening of a mailbox by two processes.  What the locking is *supposed* to do is to make one process *wait* for the other one, but what it does instead, if you don't catch the USR2 signal, is for the process that got the lock first to *die* after *being killed* by the other one.  This is not correct behavior.

Incidentally, I just tested with a newly compiled c-client 2004g and confirmed that the problem persists there without my patch.
 [2010-01-10 21:45 UTC] tdfischer at fedoraproject dot org
This bug is still around and can wreak havok for a drupal site that lets 
users submit content via machine-local mail. Could someone *please* 
commit it already?
 [2010-01-10 22:36 UTC] rasmus@php.net
The problem with PHP setting a handler for SIGUSR2 is that when we are 
running as a SAPI module inside some other process like Apache or 
anything using LinuxThreads, grabbing SIGUSR2 may cause problems.  
Newer Linux kernels provide reserved internals signals for LinuxThreads 
to use, and Apache should only be using SIGUSR1, but how confident are 
you that PHP grabbing this signal isn't going to break it in some 
environments?  It may fix the problem in yours, but if it breaks it in 
many others that is something we need to deal with.
 [2010-12-01 16:17 UTC] jani@php.net
-Package: Feature/Change Request +Package: IMAP related
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC