Failed to set socket option error in Samba 2.0.6/Solaris 7 -- finally some luck

David Collier-Brown davecb at canada.sun.com
Thu Apr 27 12:54:03 GMT 2000


For the team: Eric had suspicious "Failed to set socket option
SO_KEEPALIVE"
messages, that appeared to be an impossible condition: an fd that
was invalid.  

We added debugging statements and tracked it down this far,
and would like suggestions as to why we're seeing failures, then
successes.

If this discussion isn't suitable for samba-technical, please say! 
--dave


Eric Boehm wrote:
> Here's the error!
> 
>     [2000/04/26 09:36:37, 3] smbd/server.c:reload_services(322)
>       Client

Ok, the code at line 322 is:

       {
                extern int Client;
                if (Client != -1) {
                        set_socket_options(Client,"SO_KEEPALIVE");
                       
set_socket_options(Client,user_socket_options);
                }
        }
So the Client variable is the one we'e interested in, an it
shows as being set as follows: (this is from cscope)

  File         Function                    Line
1 util_sock.c  <global>                      36 int Client = -1;
2 clientutil.c cli_send_session_request     375 Client =
                                               
open_socket_out(SOCK_STREAM,
                                                &dest_ip, port,
                                                LONG_CONNECT_TIMEOUT);
3 clientutil.c cli_open_sockets             938 Client =
                                               
open_socket_out(SOCK_STREAM,
                                                &dest_ip, port, 
                                               
LONG_CONNECT_TIMEOUT);  
4 util_sock.c  close_sockets                191 Client = -1;
5 process.c    receive_message_or_smb       170 FD_SET(Client,&fds);
6 server.c     open_sockets_inetd            78 Client = dup(0);
7 server.c     open_sockets                 214 Client =
                                               
accept(s,&addr,&in_addrlen);

The next line of the log says we're in util_sock.c...
>     [2000/04/26 09:36:37, 10] lib/util_sock.c:set_socket_options(106)
>       in set_socket_options(8, SO_KEEPALIVE)
>     [2000/04/26 09:36:37, 0] lib/util_sock.c:set_socket_options(148)
>       Failed to set socket option SO_KEEPALIVE (Error Bad file number)

And that takes us back to the place where we know the fd (Client) is
invalid.

Let's look at reload_services in detail: 
----
BOOL reload_services(BOOL test)
{
        BOOL ret;

        if (lp_loaded()) {
                pstring fname;
                pstrcpy(fname,lp_configfile());
                if (file_exist(fname,NULL) &&
!strcsequal(fname,servicesf)) {
                        pstrcpy(servicesf,fname);
                        test = False;
                }
        }

        reopen_logs();

        if (test && !lp_file_list_changed())
                return(True);

        lp_killunused(conn_snum_used);

        ret = lp_load(servicesf,False,False,True);

        load_printers();

        /* perhaps the config filename is now set */
        if (!test)
                reload_services(True);

        reopen_logs();

        load_interfaces();

        {
                extern int Client;
                if (Client != -1) {
                        set_socket_options(Client,"SO_KEEPALIVE");
                       
set_socket_options(Client,user_socket_options);
                }
        }
--
and we blow up here.  That means Client is set to something other
than -1, and whatever that is, it's not a valid fd, as indicated by
the string of falures which follow:
>     [2000/04/26 09:36:37, 3] smbd/server.c:reload_services(324)
>       Client
>     [2000/04/26 09:36:37, 10] lib/util_sock.c:set_socket_options(106)
>       in set_socket_options(8, TCP_NODELAY SO_KEEPALIVE SO_SNDBUF=32768 SO_RCVBUF=32768)
>     [2000/04/26 09:36:37, 0] lib/util_sock.c:set_socket_options(148)
>       Failed to set socket option TCP_NODELAY (Error Bad file number)
>     [2000/04/26 09:36:37, 0] lib/util_sock.c:set_socket_options(148)
>       Failed to set socket option SO_KEEPALIVE (Error Bad file number)
>     [2000/04/26 09:36:37, 0] lib/util_sock.c:set_socket_options(148)
>       Failed to set socket option SO_SNDBUF (Error Bad file number)
>     [2000/04/26 09:36:37, 0] lib/util_sock.c:set_socket_options(148)
>       Failed to set socket option SO_RCVBUF (Error Bad file number)

After this string of errors, we then go into a string of successes!
We call open_sockets from smbd/server.c at line 214
----------
>     [2000/04/26 09:36:37, 3] smbd/server.c:open_sockets(240)
>       Client
>     [2000/04/26 09:36:37, 10] lib/util_sock.c:set_socket_options(106)
>       in set_socket_options(8, SO_KEEPALIVE)
>     [2000/04/26 09:36:37, 3] smbd/server.c:open_sockets(242)
>       Client
>     [2000/04/26 09:36:37, 10] lib/util_sock.c:set_socket_options(106)
>       in set_socket_options(8, TCP_NODELAY SO_KEEPALIVE SO_SNDBUF=32768 SO_RCVBUF=32768)
--
Let's look for asignments to Client in server code: there's one at 
open_sockets, line 214 of server.c.
---
 static BOOL open_sockets(BOOL is_daemon,int port)
	
	...many line skipped...

       /* now accept incoming connections - forking a new process
           for each incoming connection */
        DEBUG(2,("waiting for a connection\n"));
        while (1) {
                fd_set lfds;
                int num;

                memcpy((char *)&lfds, (char *)&listen_set,
                       sizeof(listen_set));

                num = sys_select(FD_SETSIZE,&lfds,NULL);

                if (num == -1 && errno == EINTR)
                        continue;

                /* check if we need to reload services */
                check_reload(time(NULL));

                /* Find the sockets that are read-ready -
                   accept on these. */
                for( ; num > 0; num--) {
                        struct sockaddr addr;
                        int in_addrlen = sizeof(addr);

                        s = -1;
                        for(i = 0; i < num_interfaces; i++) {
                                if(FD_ISSET(fd_listenset[i],&lfds)) {
                                        s = fd_listenset[i];
                                        /* Clear this so we don't look
                                           at it again. */
                                        FD_CLR(fd_listenset[i],&lfds);
                                        break;
                                }
                        }

--line 214---->         Client = accept(s,&addr,&in_addrlen);
At this point, if "s" is a valid fd, Client will be a valid fd...


                        if (Client == -1 && errno == EINTR)
                                continue;

                        if (Client == -1) {
                                DEBUG(0,("open_sockets: accept: %s\n",
                                         strerror(errno)));
                                continue;
                        }
And if it isn't, we'd get the error above!

                        if (Client != -1 && fork()==0) {
                                /* Child code ... */

                                /* close the listening socket(s) */
                                for(i = 0; i < num_interfaces; i++)
                                        close(fd_listenset[i]);

                                /* close our standard file
                                   descriptors */
                                close_low_fds();
                                am_parent = 0;

                               
set_socket_options(Client,"SO_KEEPALIVE");
                             
set_socket_options(Client,user_socket_options);
---
and this is where we now succeed.

Client is now set to something sane, and operates properly,
as shown fromthe logs of log.ipllserver3a, matching timestamp
09:36:37.
> 
>     [2000/04/26 09:36:37, 6] param/loadparm.c:lp_file_list_changed(1855)
>       lp_file_list_changed()
>       file /usr/local/samba/lib/smb.conf -> /usr/local/samba/lib/smb.conf  last mod_time: Wed Apr 26 08:36:05 2000
	
	...skip...
>     [2000/04/26 09:36:37, 6] lib/util_sock.c:write_socket(557)
>       write_socket(8,4)
>     [2000/04/26 09:36:37, 6] lib/util_sock.c:write_socket(560)
>       write_socket(8,4) wrote 4
>     [2000/04/26 09:36:48, 10] lib/util_sock.c:read_smb_length_return_keepalive(599)
>       got smb length of 170

	...and so on


I initiallu speculated that a client was failing between the accept
and the setsockopts, but this isn't the case.

The code above implies that "Client" isn't set to anything plausible
in reload_services.  Sinc it's part of server.c, but not
part iof the cleint startup stuff, I wonder if
it should be trying to set the client's fd options at all.
It's only called by server and nmbd code...
---
Functions calling this function: reload_services

  File      Function              Line
1 nmbd.c    reload_services        290 reload_services( True ); 
2 nmbd.c    process                477 reload_services( True );
3 nmbd.c    main                   760 if ( !reload_services(False) )
4 nmbd.c    main                   768 reload_services( True );
5 negprot.c reply_negprot          394 reload_services(True);
6 negprot.c reply_negprot          425 reload_services(True);
7 process.c check_reload           835 reload_services(True);
8 reply.c   reply_special          122 reload_services(True);
9 reply.c   reply_sesssetup_and_X  854 reload_services(True);
0 server.c  reload_services        308 reload_services(True);   
1 server.c  main                   656 if (!reload_services(False))
2 server.c  main                   742 reload_services(True); 
---

Eric, can you comment out this block of code in reload_services,
please?

Experts, can you recollect a reason we try to set socket options
this far away from the accept call?  We do it safely nearby in the
open_sockets code...

--dave
-- 
David Collier-Brown,  | Always do right. This will gratify some people
185 Ellerslie Ave.,   | and astonish the rest.        -- Mark Twain
Willowdale, Ontario   | //www.oreilly.com/catalog/samba/author.html
Work: (905) 415-2849 Home: (416) 223-8968 Email: davecb at canada.sun.com


More information about the samba-technical mailing list