commit 5f7c62fa4d1a3b756119f7e279c5753036c3e9d1 from: Martijn van Duren date: Mon Mar 28 14:16:09 2022 UTC pause stdout io when handling input. It's not going to be scheduled while we're still in the parsing input codepath and it causes a massive build-up of the kevent array in libevent, resulting in high memory usage never released. commit - 24587d39df0893249ec70e21ad4c1ae6384587f1 commit + 5f7c62fa4d1a3b756119f7e279c5753036c3e9d1 blob - 1aec59c37c55b000486f0ae246b34a8dfdc7b3e8 blob + 71b0691f55d1ae2f533b94e0f027e22cf510c52e --- opensmtpd.c +++ opensmtpd.c @@ -1029,6 +1029,11 @@ osmtpd_newline(struct io *io, int ev, __unused void *a } if (ev != IO_DATAIN) return; + /* + * Multiple calls to io_printf (through osmtpd_filter_dataline) can + * cause a build-up of kevents, because of event_add/event_del loop. + */ + io_pause(io_stdout, IO_OUT); while ((line = io_getline(io, &linelen)) != NULL) { if (dupsize < linelen) { if ((linedup = realloc(linedup, linelen + 1)) == NULL) @@ -1189,6 +1194,7 @@ osmtpd_newline(struct io *io, int ev, __unused void *a osmtpd_callbacks[i].osmtpd_cb(&(osmtpd_callbacks[i]), &(ctx->ctx), line, linedup); } + io_resume(io_stdout, IO_OUT); } static void