@@ -708,10 +708,72 @@ static void test_buffer (flux_reactor_t *reactor)
708708
709709struct buffer_fd_close
710710{
711+ flux_watcher_t * w ;
711712 int count ;
712713 int fd ;
713714};
714715
716+ static void buffer_decref (flux_reactor_t * r ,
717+ flux_watcher_t * w ,
718+ int revents ,
719+ void * arg )
720+ {
721+ struct buffer_fd_close * bfc = arg ;
722+ bfc -> count ++ ;
723+ flux_buffer_read_watcher_decref (bfc -> w );
724+ ok (true, "flux_buffer_read_watcher_decref" );
725+ flux_watcher_destroy (w );
726+ }
727+
728+ static void buffer_read_fd_decref (flux_reactor_t * r ,
729+ flux_watcher_t * w ,
730+ int revents ,
731+ void * arg )
732+ {
733+ struct buffer_fd_close * bfc = arg ;
734+ flux_buffer_t * fb ;
735+ const void * ptr ;
736+ int len ;
737+
738+ if (revents & FLUX_POLLERR ) {
739+ fail ("buffer decref: got FLUX_POLLERR" );
740+ return ;
741+ }
742+ if (!(revents & FLUX_POLLIN )) {
743+ fail ("buffer decref: got FLUX_POLLERR" );
744+ return ;
745+ }
746+
747+ fb = flux_buffer_read_watcher_get_buffer (w );
748+ ok ((ptr = flux_buffer_read (fb , -1 , & len )) != NULL ,
749+ "buffer decref: read from buffer success" );
750+ if (!bfc -> count ) {
751+ flux_watcher_t * w ;
752+ ok (len == 6 ,
753+ "buffer decref: read returned correct length" );
754+ ok (!memcmp (ptr , "foobar" , 6 ),
755+ "buffer decref: read returned correct data" );
756+ diag ("closing write side of read buffer" );
757+ close (bfc -> fd );
758+
759+ /* Schedule decref of read buffer
760+ */
761+ w = flux_timer_watcher_create (r , 0.01 , 0. , buffer_decref , bfc );
762+ flux_watcher_start (w );
763+ }
764+ else {
765+ ok (bfc -> count == 2 ,
766+ "buffer decref: EOF called only after manual decref" );
767+ ok ((ptr = flux_buffer_read (fb , -1 , & len )) != NULL ,
768+ "buffer decref: read from buffer success" );
769+
770+ ok (len == 0 ,
771+ "buffer decref: read returned 0, socketpair is closed" );
772+ flux_watcher_stop (w );
773+ }
774+ bfc -> count ++ ;
775+ }
776+
715777static void buffer_read_fd_close (flux_reactor_t * r , flux_watcher_t * w ,
716778 int revents , void * arg )
717779{
@@ -865,6 +927,49 @@ static void buffer_read_line_fd_close_and_left_over_data (flux_reactor_t *r,
865927 return ;
866928}
867929
930+ static void test_buffer_refcnt (flux_reactor_t * reactor )
931+ {
932+ int fd [2 ];
933+ flux_watcher_t * w ;
934+ struct buffer_fd_close bfc ;
935+
936+ /* read buffer decref test - other end closes stream */
937+
938+ ok (socketpair (PF_LOCAL , SOCK_STREAM |SOCK_NONBLOCK , 0 , fd ) == 0 ,
939+ "buffer decref: successfully created socketpair" );
940+
941+ bfc .count = 0 ;
942+ bfc .fd = fd [1 ];
943+ w = flux_buffer_read_watcher_create (reactor ,
944+ fd [0 ],
945+ 1024 ,
946+ buffer_read_fd_decref ,
947+ 0 ,
948+ & bfc );
949+ ok (w != NULL ,
950+ "buffer decref: read created" );
951+ bfc .w = w ;
952+
953+ ok (write (fd [1 ], "foobar" , 6 ) == 6 ,
954+ "buffer decref: write to socketpair success" );
955+
956+ flux_watcher_start (w );
957+
958+ diag ("calling flux_buffer_read_watcher_incref" );
959+ flux_buffer_read_watcher_incref (w );
960+
961+ ok (flux_reactor_run (reactor , 0 ) == 0 ,
962+ "buffer decref: reactor ran to completion" );
963+
964+ ok (bfc .count == 3 ,
965+ "buffer decref: read callback successfully called thrice" );
966+
967+ flux_watcher_stop (w );
968+ flux_watcher_destroy (w );
969+
970+ close (fd [0 ]);
971+ }
972+
868973static void test_buffer_corner_case (flux_reactor_t * reactor )
869974{
870975 int fd [2 ];
@@ -1521,6 +1626,7 @@ int main (int argc, char *argv[])
15211626 test_periodic (reactor );
15221627 test_fd (reactor );
15231628 test_buffer (reactor );
1629+ test_buffer_refcnt (reactor );
15241630 test_buffer_corner_case (reactor );
15251631 test_idle (reactor );
15261632 test_prepcheck (reactor );
0 commit comments