@@ -76,33 +76,29 @@ struct psr_ctx {
7676 bool psr_usemdata ;
7777};
7878
79- static void
80- ps_root_readerrorcb (void * arg , unsigned short events )
79+ static ssize_t
80+ ps_root_readerrorcb (struct psr_ctx * psr_ctx )
8181{
82- struct psr_ctx * psr_ctx = arg ;
8382 struct dhcpcd_ctx * ctx = psr_ctx -> psr_ctx ;
83+ int fd = PS_ROOT_FD (ctx );
8484 struct psr_error * psr_error = & psr_ctx -> psr_error ;
8585 struct iovec iov [] = {
8686 { .iov_base = psr_error , .iov_len = sizeof (* psr_error ) },
8787 { .iov_base = NULL , .iov_len = 0 },
8888 };
8989 ssize_t len ;
90- int exit_code = EXIT_FAILURE ;
91-
92- if (events & ELE_HANGUP )
93- goto out ;
94-
95- if (events != ELE_READ )
96- logerrx ("%s: unexpected event 0x%04x" , __func__ , events );
9790
9891#define PSR_ERROR (e ) \
9992 do { \
10093 psr_error->psr_result = -1; \
10194 psr_error->psr_errno = (e); \
102- goto out ; \
95+ return -1 ; \
10396 } while (0 /* CONSTCOND */ )
10497
105- len = recv(PS_ROOT_FD(ctx), psr_error, sizeof(*psr_error), MSG_PEEK);
98+ if (eloop_waitfd (fd ) == -1 )
99+ PSR_ERROR (errno );
100+
101+ len = recv (fd , psr_error , sizeof (* psr_error ), MSG_PEEK );
106102 if (len == -1 )
107103 PSR_ERROR (errno );
108104 else if ((size_t )len < sizeof (* psr_error ))
@@ -130,29 +126,23 @@ ps_root_readerrorcb(void *arg, unsigned short events)
130126 iov [1 ].iov_len = psr_error -> psr_datalen ;
131127 }
132128
133- len = readv (PS_ROOT_FD ( ctx ) , iov , __arraycount (iov ));
129+ len = readv (fd , iov , __arraycount (iov ));
134130 if (len == -1 )
135131 PSR_ERROR (errno );
136132 else if ((size_t )len != sizeof (* psr_error ) + psr_error -> psr_datalen )
137133 PSR_ERROR (EINVAL );
138- exit_code = EXIT_SUCCESS ;
139-
140- out :
141- eloop_exit (ctx -> ps_eloop , exit_code );
134+ return len ;
142135}
143136
144137ssize_t
145138ps_root_readerror (struct dhcpcd_ctx * ctx , void * data , size_t len )
146139{
147140 struct psr_ctx * pc = ctx -> ps_root -> psp_data ;
148- int err ;
149141
150142 pc -> psr_data = data ;
151143 pc -> psr_datalen = len ;
152144 pc -> psr_usemdata = false;
153- err = eloop_start (ctx -> ps_eloop );
154- if (err < 0 )
155- return err ;
145+ ps_root_readerrorcb (pc );
156146
157147 errno = pc -> psr_error .psr_errno ;
158148 return pc -> psr_error .psr_result ;
@@ -162,13 +152,10 @@ ssize_t
162152ps_root_mreaderror (struct dhcpcd_ctx * ctx , void * * data , size_t * len )
163153{
164154 struct psr_ctx * pc = ctx -> ps_root -> psp_data ;
165- int err ;
166155 void * d ;
167156
168157 pc -> psr_usemdata = true;
169- err = eloop_start (ctx -> ps_eloop );
170- if (err < 0 )
171- return err ;
158+ ps_root_readerrorcb (pc );
172159
173160 if (pc -> psr_error .psr_datalen != 0 ) {
174161 if (pc -> psr_error .psr_datalen > pc -> psr_mdatalen ) {
@@ -212,7 +199,7 @@ ps_root_writeerror(struct dhcpcd_ctx *ctx, ssize_t result,
212199 err = sendmsg (fd , & msg , MSG_EOR );
213200
214201 /* Error sending the message? Try sending the error of sending. */
215- if (err == -1 ) {
202+ if (err == -1 && errno != EPIPE ) {
216203 logerr ("%s: result=%zd, data=%p, len=%zu" ,
217204 __func__ , result , data , len );
218205 psr .psr_result = err ;
@@ -776,7 +763,7 @@ ps_root_signalcb(int sig, void *arg)
776763 if (!(ctx -> options & DHCPCD_EXITING ))
777764 return ;
778765 if (!(ps_waitforprocs (ctx )))
779- eloop_exit (ctx -> ps_eloop , EXIT_SUCCESS );
766+ eloop_exit (ctx -> eloop , EXIT_SUCCESS );
780767}
781768
782769int (* handle_interface )(void * , int , const char * );
@@ -888,6 +875,7 @@ ps_root_start(struct dhcpcd_ctx *ctx)
888875
889876 if (xsocketpair (AF_UNIX , SOCK_SEQPACKET | SOCK_CXNB , 0 , datafd ) == -1 )
890877 return -1 ;
878+
891879 if (ps_setbuf_fdpair (datafd ) == -1 )
892880 return -1 ;
893881#ifdef PRIVSEP_RIGHTS
@@ -916,9 +904,6 @@ ps_root_start(struct dhcpcd_ctx *ctx)
916904 }
917905
918906 psp -> psp_data = pc ;
919- if (eloop_event_add (ctx -> ps_eloop , psp -> psp_fd , ELE_READ ,
920- ps_root_readerrorcb , pc ) == -1 )
921- return -1 ;
922907
923908 if (pid == 0 ) {
924909 ctx -> ps_log_fd = logfd [0 ]; /* Keep open to pass to processes */
@@ -976,11 +961,9 @@ ps_root_stop(struct dhcpcd_ctx *ctx)
976961 struct ps_process * psp = ctx -> ps_root ;
977962 int err ;
978963
979- if (!(ctx -> options & DHCPCD_PRIVSEP ) ||
980- ctx -> eloop == NULL )
964+ if (!(ctx -> options & DHCPCD_PRIVSEP ))
981965 return 0 ;
982966
983-
984967 /* If we are the root process then remove the pidfile */
985968 if (ctx -> options & DHCPCD_PRIVSEPROOT ) {
986969 if (!(ctx -> options & DHCPCD_TEST ) && unlink (ctx -> pidfile ) == -1 )
@@ -990,12 +973,25 @@ ps_root_stop(struct dhcpcd_ctx *ctx)
990973 if (ctx -> ps_log_root_fd != -1 ) {
991974 ssize_t loglen ;
992975
976+ #ifdef __linux__
977+ /* Seems to help to get the last parts,
978+ * sched_yield(2) does not. */
979+ sleep (0 );
980+ #endif
993981 do {
994982 loglen = logreadfd (ctx -> ps_log_root_fd );
995983 } while (loglen != 0 && loglen != -1 );
984+ close (ctx -> ps_log_root_fd );
985+ ctx -> ps_log_root_fd = -1 ;
996986 }
997987 }
998988
989+ if (ctx -> ps_data_fd != -1 ) {
990+ eloop_event_delete (ctx -> eloop , ctx -> ps_data_fd );
991+ close (ctx -> ps_data_fd );
992+ ctx -> ps_data_fd = -1 ;
993+ }
994+
999995 /* Only the manager process gets past this point. */
1000996 if (ctx -> options & DHCPCD_FORKED )
1001997 return 0 ;
@@ -1015,7 +1011,8 @@ ps_root_stop(struct dhcpcd_ctx *ctx)
10151011 } /* else the root process has already exited :( */
10161012
10171013 err = ps_stopwait (ctx );
1018- ps_freeprocess (ctx -> ps_root );
1014+ if (ctx -> ps_root != NULL )
1015+ ps_freeprocess (ctx -> ps_root );
10191016 return err ;
10201017}
10211018
0 commit comments