[Dovecot] v1.1.2 released

Kyle Wheeler kyle-dovecot at memoryhole.net
Mon Aug 4 22:04:59 EEST 2008


On Monday, August  4 at 01:54 PM, quoth Timo Sirainen:
>> On Thursday, July 24 at 03:05 AM, quoth Timo Sirainen:
>>> 	+ Added a new maildirlock utility for write-locking Dovecot 	 
>>> Maildir.
>>
>> Every time I attempt to use this (as root), it exits with a return code 
>> of 143 and my shell prints out "Terminated".
>>
>> I'm guessing that what happens is a result of this:
>>
>>    /* locked - send a  */
>>    if (kill(parent_pid, SIGTERM) < 0)
>>        i_fatal("kill(parent, SIGTERM) failed: %m");
>>
>> Any idea on how I can fix it?
>
> Not really.. The parent PID should be the parent maildirlock process, 
> which also should have caught the TERM signal. You could see what happens 
> if you change all SIGTERMs to SIGHUPs for example. What shell do you 
> use? Try another one?

I use bash. I tried using CSH and it does the same thing.

I tried recompiling it after replacing all instances of SIGTERM with 
SIGHUP, and instead of printing out "Terminated", it prints out 
"Hangup" (i.e. the same problem).

The issue, I think, is that maildirlock has a race condition. There is 
no guarantee that the parent has set up its signal handlers before the 
child gets around to killing it.

To demonstrate it, I modified the source to force the child to give 
the parent some time, like this:

     if (pid != 0) {
         io_loop_run(ioloop);
         if (!success)
             return 1;
         printf("%s", dec2str(pid));
         return 0;
     } else {
         sleep(1);
     }

And that fixed the problem. Now, telling the child to sleep is 
obviously an unacceptable solution.

I think signals are probably a bad way of handling this inter-process 
communication. How about using a pipe? I've attached a patch that 
seems to work.

~Kyle
-- 
Time is an illusion. Lunchtime doubly so.
                                                       -- Douglas Adams
-------------- next part --------------
--- maildirlock.c	2008-08-04 14:03:11.000000000 -0500
+++ maildirlock-new.c	2008-08-04 14:02:55.000000000 -0500
@@ -46,6 +46,7 @@ int main(int argc, const char *argv[])
 	struct dotlock *dotlock;
 	unsigned int timeout;
 	pid_t pid, parent_pid;
+	int trigger[2];
 
 	if (argc != 3) {
 		fprintf(stderr, "Usage: maildirlock <path> <timeout>\n"
@@ -53,6 +54,10 @@ int main(int argc, const char *argv[])
 		return 1;
 	}
 	parent_pid = getpid();
+	if (pipe(trigger) != 0) {
+		fprintf(stderr, "pipe() failed: %m");
+		return 1;
+	}
 
 	pid = fork();
 	if (pid == (pid_t)-1) {
@@ -69,10 +74,11 @@ int main(int argc, const char *argv[])
 	lib_signals_set_handler(SIGCHLD, TRUE, sig_die, NULL);
 
 	if (pid != 0) {
-		/* master - wait for the child process to finish locking */
-		io_loop_run(ioloop);
-		if (!success)
+		char junk;
+		if (read(trigger[0], &junk, 1) != 1) {
+		    fprintf(stderr, "read() failed: %m");
 			return 1;
+		}
 		printf("%s", dec2str(pid));
 		return 0;
 	}
@@ -85,9 +91,9 @@ int main(int argc, const char *argv[])
 	if (maildir_lock(argv[1], timeout, &dotlock) <= 0)
 		return 1;
 
-	/* locked - send a  */
-	if (kill(parent_pid, SIGTERM) < 0)
-		i_fatal("kill(parent, SIGTERM) failed: %m");
+	/* locked - send a byte */
+	write(trigger[1], "", 1);
+
 	io_loop_run(ioloop);
 
 	file_dotlock_delete(&dotlock);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 204 bytes
Desc: not available
Url : http://dovecot.org/pipermail/dovecot/attachments/20080804/1d394d19/attachment-0001.bin 


More information about the dovecot mailing list