On Sun, Feb 26, 2012 at 02:21:59PM +0100, vx8400 wrote: > Спасибо за замечание по read/errno. Проверка делалась для конкретного > случая, чтобы дать remmina дойти до своей ошибки в glib/gtk. > Чтобы не морочиться с read(tls->ssl-> ...) и errno: > > boolean tls_disconnect(rdpTls* tls) > { > uint8 _buf_[8]; > if (tls_read(tls,_buf_,0) < 0) > fprintf(stderr,"ERROR: connection is already dead, won't call > SSL_shutdown(), returning true despite this\n"); > else > SSL_shutdown(tls->ssl); > return true; > } Всё равно там race - пакет с другой стороны может дойти уже после завершения tls_read(), и получится тот же SIGPIPE. > > Хотя в любом случае всё это не поможет, поскольку закрытие соединения > > со стороны сервера может произойти после проверки, но перед вызовом > > SSL_shutdown().  Единственный надёжный способ борьбы с проблемой - > > игнорировать сигнал SIGPIPE и обрабатывать ошибку EPIPE от write(); > > странно, почему xfreerdp этого не делает. > > Почему сам SSL_shutdown() не проверяет соединение перед записью в > сокет и доводит до SIGPIPE? Очевидно, разработчики OpenSSL рассчитывали на то, что программы, использующие эту библиотеку, будут игнорировать SIGPIPE. На самом деле, помимо signal(SIGPIPE, SIG_IGN), существует ещё несколько способов бороться с SIGPIPE, но большинство этих способов не являются универсальными и переносимыми на различные ОС (видимо, поэтому в OpenSSL ни один из них и не применяется): http://stackoverflow.com/questions/108183/how-to-prevent-sigpipes-or-handle-them-properly В glib2 тоже не стали заморачиваться с хитрыми способами, и просто всадили игнорирование SIGPIPE в инициализацию GSocket, хотя подобные глобальные изменения в библиотеках и считаются дурным тоном: http://git.altlinux.org/srpms/g/glib2.git?p=glib2.git;a=blob;f=glib/gio/gsocket.c;h=a03be77768e9d926cd31e9eafd39d5a4374d1e2f;hb=HEAD#l110 http://git.altlinux.org/srpms/g/glib2.git?p=glib2.git;a=blob;f=glib/gio/gsocket.c;h=a03be77768e9d926cd31e9eafd39d5a4374d1e2f;hb=HEAD#l704