@@ -232,18 +232,18 @@ enm_stop(ErlDrvData drv_data)
232
232
}
233
233
234
234
static int
235
- enm_do_send (EnmData * d , const struct nn_msghdr * msghdr )
235
+ enm_do_send (EnmData * d , const struct nn_msghdr * msghdr , int * err )
236
236
{
237
- int rc , err ;
237
+ int rc ;
238
238
239
239
if (msghdr -> msg_iovlen == 0 )
240
240
return 0 ;
241
- err = 0 ;
241
+ * err = 0 ;
242
242
do {
243
243
rc = nn_sendmsg (d -> fd , msghdr , NN_DONTWAIT );
244
244
if (rc < 0 ) {
245
- err = errno ;
246
- switch (err ) {
245
+ * err = errno ;
246
+ switch (* err ) {
247
247
case EINTR :
248
248
case EFSM :
249
249
/* do nothing */
@@ -254,10 +254,10 @@ enm_do_send(EnmData* d, const struct nn_msghdr* msghdr)
254
254
default :
255
255
enm_write_select (d , 0 );
256
256
enm_read_select (d , 0 );
257
- driver_failure (d -> port , err );
257
+ driver_failure (d -> port , * err );
258
258
}
259
259
}
260
- } while (err == EINTR );
260
+ } while (* err == EINTR );
261
261
return rc ;
262
262
}
263
263
@@ -280,9 +280,8 @@ enm_outputv(ErlDrvData drv_data, ErlIOVec *ev)
280
280
msghdr .msg_control = 0 ;
281
281
err = 0 ;
282
282
do {
283
- rc = enm_do_send (d , & msghdr );
283
+ rc = enm_do_send (d , & msghdr , & err );
284
284
if (rc < 0 ) {
285
- err = errno ;
286
285
if (err == EAGAIN ) {
287
286
d -> b .writable = 0 ;
288
287
break ;
@@ -304,9 +303,8 @@ enm_outputv(ErlDrvData drv_data, ErlIOVec *ev)
304
303
msghdr .msg_control = 0 ;
305
304
err = 0 ;
306
305
do {
307
- rc = enm_do_send (d , & msghdr );
306
+ rc = enm_do_send (d , & msghdr , & err );
308
307
if (rc < 0 ) {
309
- err = errno ;
310
308
if (err == EAGAIN ) {
311
309
d -> b .writable = 0 ;
312
310
break ;
@@ -817,7 +815,7 @@ enm_ready_output(ErlDrvData drv_data, ErlDrvEvent event)
817
815
struct nn_msghdr msghdr ;
818
816
ErlIOVec ev ;
819
817
ErlDrvSizeT total ;
820
- int rc ;
818
+ int rc , err ;
821
819
822
820
d -> b .writable = 1 ;
823
821
total = driver_peekqv (d -> port , & ev );
@@ -827,7 +825,19 @@ enm_ready_output(ErlDrvData drv_data, ErlDrvEvent event)
827
825
msghdr .msg_iov = (struct nn_iovec * )ev .iov ;
828
826
msghdr .msg_iovlen = ev .vsize ;
829
827
msghdr .msg_control = 0 ;
830
- rc = enm_do_send (d , & msghdr );
828
+ rc = enm_do_send (d , & msghdr , & err );
829
+ if (rc < 0 && err == EAGAIN ) {
830
+ /* enm_ready_output (this function) is called when the VM's
831
+ select/poll/etc. indicates the socket has become writable, but
832
+ if we get here, it means we tried to write but it failed with
833
+ EAGAIN, indicating that the socket isn't writable after all. So
834
+ we assume things are broken in this case, and signal eof. */
835
+ enm_write_select (d , 0 );
836
+ enm_read_select (d , 0 );
837
+ nn_close (d -> fd );
838
+ d -> fd = d -> sfd = d -> rfd = -1 ;
839
+ driver_failure_eof (d -> port );
840
+ }
831
841
if (rc > 0 )
832
842
driver_deq (d -> port , rc );
833
843
if (rc == total && d -> b .writable ) {
0 commit comments