I have been trying to use the command hook api in an experimental plugin I have written. The hook is registered using the command_hook_register function, and for most commands my hook functions get called once as expected. But when the client uses one of the "UID" commands (e.g. "UID FETCH" ) the hook functions are executed twice. I am using dovecot version 2.1.12. Am I correct in thinking this is a bug? If I am wrong and this is the intended behaviour, how should I detect whether the hook function call is the first or second for a client's command (in particular for the 'post command' hook)? Assuming it is a bug, I modified the code in the command_exec function to stop the second hook call, a patch for this is below. This appears to apply to later dovecot releases as well. I am happy for this code to be included in future releases of dovecot. Thanks, Tony. diff -ur -x .deps -x Makefile dovecot-2.1.12-orig/src/imap/imap-commands.c dovecot-2.1.12-mod/src/imap/imap-commands.c --- dovecot-2.1.12-orig/src/imap/imap-commands.c 2012-03-22 12:59:17.000000000 +0000 +++ dovecot-2.1.12-mod/src/imap/imap-commands.c 2013-02-20 17:15:50.000000000 +0000 @@ -38,7 +38,7 @@ { "FETCH", cmd_fetch, COMMAND_FLAG_USES_SEQS }, { "SEARCH", cmd_search, COMMAND_FLAG_USES_SEQS }, { "STORE", cmd_store, COMMAND_FLAG_USES_SEQS }, - { "UID", cmd_uid, 0 }, + { "UID", cmd_uid, COMMAND_FLAG_HOOKS_DELAY }, { "UID COPY", cmd_copy, COMMAND_FLAG_BREAKS_SEQS }, { "UID FETCH", cmd_fetch, COMMAND_FLAG_BREAKS_SEQS }, { "UID SEARCH", cmd_search, COMMAND_FLAG_BREAKS_SEQS }, @@ -142,12 +142,20 @@ { const struct command_hook *hook; bool ret; + bool exec_hooks = FALSE; - array_foreach(&command_hooks, hook) - hook->pre(cmd); + if ( !(cmd->cmd_flags & COMMAND_FLAG_HOOKS_DELAY)) { + exec_hooks = TRUE; + array_foreach(&command_hooks, hook) + hook->pre(cmd); + } ret = cmd->func(cmd); - array_foreach(&command_hooks, hook) - hook->post(cmd); + + if (exec_hooks != FALSE) + { + array_foreach(&command_hooks, hook) + hook->post(cmd); + } return ret; } diff -ur -x .deps -x Makefile dovecot-2.1.12-orig/src/imap/imap-commands.h dovecot-2.1.12-mod/src/imap/imap-commands.h --- dovecot-2.1.12-orig/src/imap/imap-commands.h 2011-12-13 11:35:28.000000000 +0000 +++ dovecot-2.1.12-mod/src/imap/imap-commands.h 2013-02-20 17:15:44.000000000 +0000 @@ -30,7 +30,9 @@ Dovecot internally returns it for all kinds of commands, but unfortunately RFC 5530 specifies it only for "delete something" operations. */ - COMMAND_FLAG_USE_NONEXISTENT = 0x10 + COMMAND_FLAG_USE_NONEXISTENT = 0x10, + /* Set when need to delay command hook function calls due to recursive command_exec() */ + COMMAND_FLAG_HOOKS_DELAY = 0x20 }; struct command {