Issue 7937 - back-sock does not flush data to socket
Summary: back-sock does not flush data to socket
Status: VERIFIED FIXED
Alias: None
Product: OpenLDAP
Classification: Unclassified
Component: slapd (show other issues)
Version: 2.4.39
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: OpenLDAP project
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-09-11 02:15 UTC by pdg@uow.edu.au
Modified: 2014-10-23 07:35 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description pdg@uow.edu.au 2014-09-11 02:15:37 UTC
Full_Name: Peter Gray
Version: 2.4.39
OS: solaris 10
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (130.130.37.84)


The code in back-sock seems to have an error.

It opens a socket, converts the socket fd to a FILE *, and uses fprintf to send
data to the socket. For example, from search.c:


        fprintf( fp, "SEARCH\n" );
        fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
        sock_print_conn( fp, op->o_conn, si );
        sock_print_suffixes( fp, op->o_bd );
        fprintf( fp, "base: %s\n", op->o_req_dn.bv_val );
        fprintf( fp, "scope: %d\n", op->oq_search.rs_scope );
        fprintf( fp, "deref: %d\n", op->oq_search.rs_deref );
        fprintf( fp, "sizelimit: %d\n", op->oq_search.rs_slimit );
        fprintf( fp, "timelimit: %d\n", op->oq_search.rs_tlimit );
        fprintf( fp, "filter: %s\n", op->_s_search.rs_filterstr.bv_val );
        fprintf( fp, "attrsonly: %d\n", op->oq_search.rs_attrsonly ? 1 : 0 );
        fprintf( fp, "attrs:%s", op->oq_search.rs_attrs == NULL ? " all" : ""
);
        for ( an = op->oq_search.rs_attrs; an && an->an_name.bv_val; an++ ) {
                fprintf( fp, " %s", an->an_name.bv_val );
        }
        fprintf( fp, "\n\n" );  /* end of attr line plus blank line */

        /* read in the results and send them along */
        rs->sr_attrs = op->oq_search.rs_attrs;
        sock_read_and_send_results( op, rs, fp );

However, it fails to flush the stream, so in sock_read_and_send_results when it
issues a read from the socket, the data written has not been seen by the socket
endpoint. 

This results in deadlock when slapd is waiting on the read, and the daemon on
the other end of the socket is waiting on the ldap query.

My fix is to call fflush as the first operation on sock_read_and_send_results
and this worked fine.

Here is the diff.
*** .snapshot/nightly.0/result.c        Sun Jan 26 00:36:15 2014
--- result.c    Thu Sep 11 11:25:07 2014
***************
*** 48,53 ****
--- 48,54 ----
        char    line[BUFSIZ];
        char    ebuf[128];
  
+       (void) fflush(fp);
        /* read in the result and send it along */
        buf = (char *) ch_malloc( BUFSIZ );
        buf[0] = '\0';

Comment 1 Howard Chu 2014-09-11 09:24:51 UTC
pdg@uow.edu.au wrote:
> Full_Name: Peter Gray
> Version: 2.4.39
> OS: solaris 10
> URL: ftp://ftp.openldap.org/incoming/
> Submission from: (NULL) (130.130.37.84)
>
>
> The code in back-sock seems to have an error.
>
> It opens a socket, converts the socket fd to a FILE *, and uses fprintf to send
> data to the socket. For example, from search.c:

Thanks for the report, fixed in git master.
>
>
>          fprintf( fp, "SEARCH\n" );
>          fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
>          sock_print_conn( fp, op->o_conn, si );
>          sock_print_suffixes( fp, op->o_bd );
>          fprintf( fp, "base: %s\n", op->o_req_dn.bv_val );
>          fprintf( fp, "scope: %d\n", op->oq_search.rs_scope );
>          fprintf( fp, "deref: %d\n", op->oq_search.rs_deref );
>          fprintf( fp, "sizelimit: %d\n", op->oq_search.rs_slimit );
>          fprintf( fp, "timelimit: %d\n", op->oq_search.rs_tlimit );
>          fprintf( fp, "filter: %s\n", op->_s_search.rs_filterstr.bv_val );
>          fprintf( fp, "attrsonly: %d\n", op->oq_search.rs_attrsonly ? 1 : 0 );
>          fprintf( fp, "attrs:%s", op->oq_search.rs_attrs == NULL ? " all" : ""
> );
>          for ( an = op->oq_search.rs_attrs; an && an->an_name.bv_val; an++ ) {
>                  fprintf( fp, " %s", an->an_name.bv_val );
>          }
>          fprintf( fp, "\n\n" );  /* end of attr line plus blank line */
>
>          /* read in the results and send them along */
>          rs->sr_attrs = op->oq_search.rs_attrs;
>          sock_read_and_send_results( op, rs, fp );
>
> However, it fails to flush the stream, so in sock_read_and_send_results when it
> issues a read from the socket, the data written has not been seen by the socket
> endpoint.
>
> This results in deadlock when slapd is waiting on the read, and the daemon on
> the other end of the socket is waiting on the ldap query.
>
> My fix is to call fflush as the first operation on sock_read_and_send_results
> and this worked fine.
>
> Here is the diff.
> *** .snapshot/nightly.0/result.c        Sun Jan 26 00:36:15 2014
> --- result.c    Thu Sep 11 11:25:07 2014
> ***************
> *** 48,53 ****
> --- 48,54 ----
>          char    line[BUFSIZ];
>          char    ebuf[128];
>
> +       (void) fflush(fp);
>          /* read in the result and send it along */
>          buf = (char *) ch_malloc( BUFSIZ );
>          buf[0] = '\0';
>
>
>
>


-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 2 Howard Chu 2014-09-12 00:11:00 UTC
changed notes
changed state Open to Test
moved from Incoming to Software Bugs
Comment 3 Quanah Gibson-Mount 2014-09-13 21:27:45 UTC
changed notes
changed state Test to Release
Comment 4 OpenLDAP project 2014-10-23 07:35:25 UTC
fixed in master
fixed in RE25
fixed in RE24
Comment 5 Quanah Gibson-Mount 2014-10-23 07:35:25 UTC
changed notes
changed state Release to Closed