@@ -30,7 +30,8 @@ void base_process_service::do_smooth_recovery() noexcept
3030
3131bool base_process_service::bring_up () noexcept
3232{
33- if (!open_socket ()) {
33+ if (!open_socket () || !open_ready_socket ()) {
34+ becoming_inactive ();
3435 return false ;
3536 }
3637
@@ -152,7 +153,7 @@ bool base_process_service::start_ps_process(const std::vector<const char *> &cmd
152153
153154 int control_socket[2 ] = {-1 , -1 };
154155 int notify_pipe[2 ] = {-1 , -1 };
155- bool have_notify = !notification_var.empty () || force_notification_fd != -1 ;
156+ bool have_notify = !notification_var.empty () || ready_socket_fd >= 0 || force_notification_fd != -1 ;
156157 ready_notify_watcher * rwatcher = have_notify ? get_ready_watcher () : nullptr ;
157158 bool ready_watcher_registered = false ;
158159
@@ -175,7 +176,7 @@ bool base_process_service::start_ps_process(const std::vector<const char *> &cmd
175176 }
176177 }
177178
178- if (have_notify) {
179+ if (have_notify && ready_socket_fd < 0 ) {
179180 // Create a notification pipe:
180181 if (bp_sys::pipe2 (notify_pipe, 0 ) != 0 ) {
181182 log (loglevel_t ::ERROR, get_name (), " : can't create notification pipe: " , strerror (errno));
@@ -185,10 +186,14 @@ bool base_process_service::start_ps_process(const std::vector<const char *> &cmd
185186 // Set the read side as close-on-exec:
186187 int fdflags = bp_sys::fcntl (notify_pipe[0 ], F_GETFD);
187188 bp_sys::fcntl (notify_pipe[0 ], F_SETFD, fdflags | FD_CLOEXEC);
189+ } else if (have_notify) {
190+ notification_var = " NOTIFY_SOCKET=" + ready_socket_path;
191+ }
188192
193+ if (have_notify) {
189194 // add, but don't yet enable, readiness watcher:
190195 try {
191- rwatcher->add_watch (event_loop, notify_pipe[0 ], dasynq::IN_EVENTS, false );
196+ rwatcher->add_watch (event_loop, ready_socket_fd >= 0 ? ready_socket_fd : notify_pipe[0 ], dasynq::IN_EVENTS, false );
192197 ready_watcher_registered = true ;
193198 }
194199 catch (std::exception &exc) {
@@ -251,7 +256,7 @@ bool base_process_service::start_ps_process(const std::vector<const char *> &cmd
251256 run_params.unmask_sigint = onstart_flags.unmask_intr ;
252257 run_params.csfd = control_socket[1 ];
253258 run_params.socket_fd = socket_fd;
254- run_params.notify_fd = notify_pipe[1 ];
259+ run_params.notify_fd = ready_socket_fd >= 0 ? ready_socket_fd : notify_pipe[1 ];
255260 run_params.force_notify_fd = force_notification_fd;
256261 run_params.notify_var = notification_var.c_str ();
257262 run_params.env_file = env_file.c_str ();
@@ -469,86 +474,116 @@ void base_process_service::becoming_inactive() noexcept
469474 close (socket_fd);
470475 socket_fd = -1 ;
471476 }
472- }
473-
474- bool base_process_service::open_socket () noexcept
475- {
476- if (socket_path.empty () || socket_fd != -1 ) {
477- // No socket, or already open
478- return true ;
477+ if (ready_socket_fd != -1 ) {
478+ close (ready_socket_fd);
479+ ready_socket_fd = -1 ;
479480 }
481+ free (ready_socket_name);
482+ ready_socket_name = nullptr ;
483+ }
480484
481- const char * saddrname = socket_path. c_str ();
482-
485+ static int open_sock ( const char *path, const std::string &svcname, int type,
486+ uid_t uid, gid_t gid, int perms, struct sockaddr_un *&name) noexcept {
483487 // Check the specified socket path
484488 struct stat stat_buf;
485- if (stat (saddrname , &stat_buf) == 0 ) {
489+ if (stat (path , &stat_buf) == 0 ) {
486490 if ((stat_buf.st_mode & S_IFSOCK) == 0 ) {
487491 // Not a socket
488- log (loglevel_t ::ERROR, get_name () , " : activation socket file exists (and is not a socket)" );
489- return false ;
492+ log (loglevel_t ::ERROR, svcname , " : socket file exists (and is not a socket)" );
493+ return - 1 ;
490494 }
491495 }
492496 else if (errno != ENOENT) {
493497 // Other error
494- log (loglevel_t ::ERROR, get_name () , " : error checking activation socket: " , strerror (errno));
495- return false ;
498+ log (loglevel_t ::ERROR, svcname , " : error checking socket: " , strerror (errno));
499+ return - 1 ;
496500 }
497501
498502 // Remove stale socket file (if it exists).
499503 // We won't test the return from unlink - if it fails other than due to ENOENT, we should get an
500504 // error when we try to create the socket anyway.
501- unlink (saddrname );
505+ unlink (path );
502506
503- uint sockaddr_size = offsetof (struct sockaddr_un , sun_path) + socket_path. length ( ) + 1 ;
504- struct sockaddr_un * name = static_cast <sockaddr_un *>(malloc (sockaddr_size));
507+ uint sockaddr_size = offsetof (struct sockaddr_un , sun_path) + strlen (path ) + 1 ;
508+ name = static_cast <sockaddr_un *>(malloc (sockaddr_size));
505509 if (name == nullptr ) {
506- log (loglevel_t ::ERROR, get_name () , " : opening activation socket: out of memory" );
507- return false ;
510+ log (loglevel_t ::ERROR, svcname , " : opening socket: out of memory" );
511+ return - 1 ;
508512 }
509513
510514 name->sun_family = AF_UNIX;
511- strcpy (name->sun_path , saddrname );
515+ strcpy (name->sun_path , path );
512516
513- int sockfd = dinit_socket (AF_UNIX, SOCK_STREAM , 0 , SOCK_NONBLOCK | SOCK_CLOEXEC);
517+ int sockfd = dinit_socket (AF_UNIX, type , 0 , SOCK_NONBLOCK | SOCK_CLOEXEC);
514518 if (sockfd == -1 ) {
515- log (loglevel_t ::ERROR, get_name () , " : error creating activation socket: " , strerror (errno));
519+ log (loglevel_t ::ERROR, svcname , " : error creating socket: " , strerror (errno));
516520 free (name);
517- return false ;
521+ return - 1 ;
518522 }
519523
520524 if (bind (sockfd, (struct sockaddr *) name, sockaddr_size) == -1 ) {
521- log (loglevel_t ::ERROR, get_name () , " : error binding activation socket: " , strerror (errno));
525+ log (loglevel_t ::ERROR, svcname , " : error binding socket: " , strerror (errno));
522526 close (sockfd);
523527 free (name);
524- return false ;
528+ return - 1 ;
525529 }
526530
527- free (name);
528-
529531 // POSIX (1003.1, 2013) says that fchown and fchmod don't necessarily work on sockets. We have to
530532 // use chown and chmod instead.
531- if (chown (saddrname, socket_uid, socket_gid )) {
532- log (loglevel_t ::ERROR, get_name () , " : error setting activation socket owner/group: " ,
533+ if (chown (path, uid, gid )) {
534+ log (loglevel_t ::ERROR, svcname , " : error setting socket owner/group: " ,
533535 strerror (errno));
534536 close (sockfd);
535- return false ;
537+ return - 1 ;
536538 }
537539
538- if (chmod (saddrname, socket_perms ) == -1 ) {
539- log (loglevel_t ::ERROR, get_name () , " : Error setting activation socket permissions: " ,
540+ if (chmod (path, perms ) == -1 ) {
541+ log (loglevel_t ::ERROR, svcname , " : Error setting socket permissions: " ,
540542 strerror (errno));
541543 close (sockfd);
542- return false ;
544+ return - 1 ;
543545 }
544546
545- if (listen (sockfd, 128 ) == -1 ) { // 128 "seems reasonable".
546- log (loglevel_t ::ERROR, " : error listening on activation socket: " , strerror (errno));
547+ if (type != SOCK_DGRAM && listen (sockfd, 128 ) == -1 ) { // 128 "seems reasonable".
548+ log (loglevel_t ::ERROR, " : error listening on socket: " , strerror (errno));
547549 close (sockfd);
550+ return -1 ;
551+ }
552+
553+ return sockfd;
554+ }
555+
556+ bool base_process_service::open_socket () noexcept
557+ {
558+ if (socket_path.empty () || socket_fd != -1 ) {
559+ // No socket, or already open
560+ return true ;
561+ }
562+
563+ struct sockaddr_un *name = nullptr ;
564+ socket_fd = open_sock (socket_path.c_str (), get_name (), SOCK_STREAM, socket_uid,
565+ socket_gid, socket_perms, name);
566+ free (name);
567+
568+ return socket_fd >= 0 ;
569+ }
570+
571+ bool base_process_service::open_ready_socket () noexcept
572+ {
573+ if (ready_socket_path.empty () || ready_socket_fd != -1 ) {
574+ // No socket, or already open
575+ return true ;
576+ }
577+
578+ ready_socket_fd = open_sock (ready_socket_path.c_str (), get_name (), SOCK_DGRAM,
579+ ready_socket_uid, ready_socket_gid, ready_socket_perms, ready_socket_name);
580+
581+ if (ready_socket_fd < 0 ) {
582+ free (ready_socket_name);
583+ ready_socket_name = nullptr ;
548584 return false ;
549585 }
550586
551- socket_fd = sockfd;
552587 return true ;
553588}
554589
0 commit comments