[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