Hi Timo, Just wanted to let you know that the mail/dovecot24 port I proposed — including the hibernate patch you provided — was officially committed to the main FreeBSD ports tree today. Thanks again for your help! Best regards, Jordan
On 6 Aug 2026, at 1:31, Jordan Ostrev <jordan@ostreff.info> wrote:
Hi Timo, I tested your patch on FreeBSD 15.x and can confirm that it completely resolves the issue. Test scenario:
1. Connected via telnet localhost 143, authenticated, selected INBOX, and issued A03 IDLE. 2. Verified via doveadm who that after the hibernation timeout, the session successfully transitioned from imap to imap-hibernate (jordan@ostreff.info 1 imap-hibernate (PID) (127.0.0.1)). 3. Sent a test email from an external server — the hibernated session woke up instantly, received the real-time notification (* 4297 EXISTS), and returned to the imap service without dropping the connection. 4. Checked the system logs — no more Invalid peer_dev_major value errors.
Everything works as expected - tested it more than once to hibernate. Thanks for the fix! You can follow what happens with FreeBSD PR on https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=286695. It will be great if you can follow the thread.
KR, Jordan
PS.
A02 SELECT INBOX * FLAGS (\Answered \Flagged \Deleted \Seen \Draft unknown-1 unknown-2 unknown-4 unknown-8 unknown-5 unknown-7 unknown-3 unknown-10 $NotJunk NotJunk $Forwarded Forwarded $Junk Junk $label1 JunkRecorded $MailFlagBit0 NonJunk) * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft unknown-1 unknown-2 unknown-4 unknown-8 unknown-5 unknown-7 unknown-3 unknown-10 $NotJunk NotJunk $Forwarded Forwarded $Junk Junk $label1 JunkRecorded $MailFlagBit0 NonJunk \*)] Flags permitted. * 4296 EXISTS * 0 RECENT * OK [UNSEEN 1] First unseen. * OK [UIDVALIDITY 1610577026] UIDs valid * OK [UIDNEXT 95301] Predicted next UID * OK [HIGHESTMODSEQ 16189] Highest A02 OK [READ-WRITE] Select completed (0.006 + 0.000 + 0.005 secs). A03 IDLE + idling * OK Still here * OK Still here * OK Still here * OK Still here * OK Still here * OK Still here * 4297 EXISTS * 1 RECENT * 4297 FETCH (FLAGS (\Recent $NotJunk NotJunk)) * OK Still here * OK Still here * OK Still here * OK Still here * OK Still here * OK Still here
# doveadm who username # service (pids) (ips) jordan@ostreff.info 3 imap (4315 5394 3153) (46.10.221.52) jordan@ostreff.info 1 imap-hibernate (4351) (127.0.0.1)
# doveadm who username # service (pids) (ips) jordan@ostreff.info 4 imap (4315 5632 5394 3153) (46.10.221.52 127.0.0.1)
and here it goes again to hibernate 2nd time: # doveadm who username # service (pids) (ips) jordan@ostreff.info 4 imap (7247 6707 5999 3153) (46.10.221.52) jordan@ostreff.info 1 imap-hibernate (6686) (127.0.0.1)
Telnet session never disconnected or frozen somehow.
# cat /usr/ports/mail/dovecot24/files/patch-src_imap_imap-client-hibernate.c --- src/imap/imap-client-hibernate.c.orig 2026-08-05 21:51:45 UTC +++ src/imap/imap-client-hibernate.c @@ -62,7 +62,8 @@ static void imap_hibernate_write_cmd(struct client *cl str_append_tabescaped(cmd, user->set->unexpanded_mail_log_prefix); str_printfa(cmd, "\tidle_notify_interval=%u", client->set->imap_idle_notify_interval); - if (fstat(client->fd_in, &peer_st) == 0) { + if (fstat(client->fd_in, &peer_st) == 0 && + peer_st.st_dev != (dev_t)-1) { str_printfa(cmd, "\tpeer_dev_major=%lu\tpeer_dev_minor=%lu\tpeer_ino=%llu", (unsigned long)major(peer_st.st_dev), (unsigned long)minor(peer_st.st_dev),
On 6 Aug 2026, at 0:46, Jordan Ostrev <jordan@ostreff.info> wrote:
Hi,
I'm not a kernel developer, but I checked how FreeBSD handles socket stats (soo_stat() in sys/kern/sys_socket.c). On FreeBSD, fstat() on a socket returns st_dev = NODEV and st_ino = 0. Since st_ino is always 0 for sockets, it isn't unique or usable for verification either. So your proposed patch to skip the entire check when st_dev == (dev_t)-1 is indeed the right approach.
KR, Jordan
On 5 Aug 2026, at 23:56, Timo Sirainen <timo@sirainen.com> wrote:
Hi,
I'm mainly wondering if the device is NODEV, is the inode still usable or is that also some 0 or -1? This is likely a simpler patch, but it also removes the inode check also, which isn't good if it would be usable:
diff --git a/src/imap/imap-client-hibernate.c b/src/imap/imap-client-hibernate.c index cb640c3695..191b0cfef9 100644 --- a/src/imap/imap-client-hibernate.c +++ b/src/imap/imap-client-hibernate.c @@ -62,7 +62,10 @@ static void imap_hibernate_write_cmd(struct client *client, string_t *cmd, str_append_tabescaped(cmd, user->set->unexpanded_mail_log_prefix); str_printfa(cmd, "\tidle_notify_interval=%u", client->set->imap_idle_notify_interval); - if (fstat(client->fd_in, &peer_st) == 0) { + /* e.g. FreeBSD returns NODEV as sockets' st_dev, which can't be + used for verifying that the fd is the expected one. */ + if (fstat(client->fd_in, &peer_st) == 0 && + peer_st.st_dev != (dev_t)-1) { str_printfa(cmd, "\tpeer_dev_major=%lu\tpeer_dev_minor=%lu\tpeer_ino=%llu", (unsigned long)major(peer_st.st_dev), (unsigned long)minor(peer_st.st_dev),
Hi Timo, Just wanted to let you know that the mail/dovecot24 port I proposed -- including the hibernate patch you provided -- was officially committed to the main FreeBSD ports tree today. Thanks again for your help! Best regards, Jordan On 6 Aug 2026, at 1:31, Jordan Ostrev <jordan@ostreff.info> wrote: Hi Timo, I tested your patch on FreeBSD 15.x and can confirm that it completely resolves the issue. Test scenario: 1. Connected via telnet localhost 143, authenticated, selected INBOX, and issued A03 IDLE. 2. Verified via doveadm who that after the hibernation timeout, the session successfully transitioned from imap to imap-hibernate (jordan@ostreff.info 1 imap-hibernate (PID) (127.0.0.1)). 3. Sent a test email from an external server -- the hibernated session woke up instantly, received the real-time notification (* 4297 EXISTS), and returned to the imap service without dropping the connection. 4. Checked the system logs -- no more Invalid peer_dev_major value errors. Everything works as expected - tested it more than once to hibernate. Thanks for the fix! You can follow what happens with FreeBSD PR on https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=286695. It will be great if you can follow the thread. KR, Jordan PS. A02 SELECT INBOX * FLAGS (\Answered \Flagged \Deleted \Seen \Draft unknown-1 unknown-2 unknown-4 unknown-8 unknown-5 unknown-7 unknown-3 unknown-10 $NotJunk NotJunk $Forwarded Forwarded $Junk Junk $label1 JunkRecorded $MailFlagBit0 NonJunk) * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft unknown-1 unknown-2 unknown-4 unknown-8 unknown-5 unknown-7 unknown-3 unknown-10 $NotJunk NotJunk $Forwarded Forwarded $Junk Junk $label1 JunkRecorded $MailFlagBit0 NonJunk \*)] Flags permitted. * 4296 EXISTS * 0 RECENT * OK [UNSEEN 1] First unseen. * OK [UIDVALIDITY 1610577026] UIDs valid * OK [UIDNEXT 95301] Predicted next UID * OK [HIGHESTMODSEQ 16189] Highest A02 OK [READ-WRITE] Select completed (0.006 + 0.000 + 0.005 secs). A03 IDLE + idling * OK Still here * OK Still here * OK Still here * OK Still here * OK Still here * OK Still here * 4297 EXISTS * 1 RECENT * 4297 FETCH (FLAGS (\Recent $NotJunk NotJunk)) * OK Still here * OK Still here * OK Still here * OK Still here * OK Still here * OK Still here # doveadm who username # service (pids) (ips) jordan@ostreff.info 3 imap (4315 5394 3153) (46.10.221.52) jordan@ostreff.info 1 imap-hibernate (4351) (127.0.0.1) # doveadm who username # service (pids) (ips) jordan@ostreff.info 4 imap (4315 5632 5394 3153) (46.10.221.52 127.0.0.1) and here it goes again to hibernate 2nd time: # doveadm who username # service (pids) (ips) jordan@ostreff.info 4 imap (7247 6707 5999 3153) (46.10.221.52) jordan@ostreff.info 1 imap-hibernate (6686) (127.0.0.1) Telnet session never disconnected or frozen somehow. # cat /usr/ports/mail/dovecot24/files/patch-src_imap_imap-client-hibernate.c --- src/imap/imap-client-hibernate.c.orig 2026-08-05 21:51:45 UTC +++ src/imap/imap-client-hibernate.c @@ -62,7 +62,8 @@ static void imap_hibernate_write_cmd(struct client *cl str_append_tabescaped(cmd, user->set->unexpanded_mail_log_prefix); str_printfa(cmd, "\tidle_notify_interval=%u", client->set->imap_idle_notify_interval); - if (fstat(client->fd_in, &peer_st) == 0) { + if (fstat(client->fd_in, &peer_st) == 0 && + peer_st.st_dev != (dev_t)-1) { str_printfa(cmd, "\tpeer_dev_major=%lu\tpeer_dev_minor=%lu\tpeer_ino=%llu", (unsigned long)major(peer_st.st_dev), (unsigned long)minor(peer_st.st_dev), On 6 Aug 2026, at 0:46, Jordan Ostrev <jordan@ostreff.info> wrote: Hi, I'm not a kernel developer, but I checked how FreeBSD handles socket stats (soo_stat() in sys/kern/sys_socket.c). On FreeBSD, fstat() on a socket returns st_dev = NODEV and st_ino = 0. Since st_ino is always 0 for sockets, it isn't unique or usable for verification either. So your proposed patch to skip the entire check when st_dev == (dev_t)-1 is indeed the right approach. KR, Jordan On 5 Aug 2026, at 23:56, Timo Sirainen <timo@sirainen.com> wrote: Hi, I'm mainly wondering if the device is NODEV, is the inode still usable or is that also some 0 or -1? This is likely a simpler patch, but it also removes the inode check also, which isn't good if it would be usable: diff --git a/src/imap/imap-client-hibernate.c b/src/imap/imap-client-hibernate.c index cb640c3695..191b0cfef9 100644 --- a/src/imap/imap-client-hibernate.c +++ b/src/imap/imap-client-hibernate.c @@ -62,7 +62,10 @@ static void imap_hibernate_write_cmd(struct client *client, string_t *cmd, str_append_tabescaped(cmd, user->set->unexpanded_mail_log_prefix); str_printfa(cmd, "\tidle_notify_interval=%u", client->set->imap_idle_notify_interval); - if (fstat(client->fd_in, &peer_st) == 0) { + /* e.g. FreeBSD returns NODEV as sockets' st_dev, which can't be + used for verifying that the fd is the expected one. */ + if (fstat(client->fd_in, &peer_st) == 0 && + peer_st.st_dev != (dev_t)-1) { str_printfa(cmd, "\tpeer_dev_major=%lu\tpeer_dev_minor=%lu\tpeer_ino=%llu", (unsigned long)major(peer_st.st_dev), (unsigned long)minor(peer_st.st_dev),