Skip to content

Conversation

@N-R-K
Copy link
Contributor

@N-R-K N-R-K commented Feb 11, 2026

currently trying to stop a service as non-root prints:

* ERROR: ${service} stopped by something else

but this is plain wrong, the service isn't stopped and the real reason for failure is due to permission problem. same issue with starting a service.

Copy link
Contributor Author

@N-R-K N-R-K left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rough draft, fixes the immediate issue but I didn't analyze it properly to make sure if the logic is wholly correct or not.

Comment on lines 636 to 639
/* FIXME: service_start() can return -1 in case of failure */
pid = service_start(svc->value);
if (!rc_conf_yesno("rc_parallel"))
rc_waitpid(pid);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed this, we might be feeding -1 into rc_waitpid which looks very suspicious to me. More investigation is needed.

@navi-desu
Copy link
Member

i swear i had a fix for this somewhere already, though i guess i never merged it

thanks for the mr!

@N-R-K
Copy link
Contributor Author

N-R-K commented Feb 11, 2026

One more issue still remaining:

[openrc errmsg-fix]~> rc-service ${service} stop
 * ${service}: failed to acquire lock: Permission denied
[openrc errmsg-fix]~> doas rc-service ${service} stop
 * WARNING: ${service} is already stopped
[openrc errmsg-fix]~> rc-service ${service} status
 * status: stopped

It's kind of a troll to complain to the user about invalid permissions, misleading them to retry with root only to then tell them the service is already stopped - which we could've known without needing root perm as shown in the status call.

@N-R-K N-R-K marked this pull request as ready for review February 11, 2026 15:34
@navi-desu
Copy link
Member

navi-desu commented Feb 11, 2026

One more issue still remaining:

[openrc errmsg-fix]~> rc-service ${service} stop
 * ${service}: failed to acquire lock: Permission denied
[openrc errmsg-fix]~> doas rc-service ${service} stop
 * WARNING: ${service} is already stopped
[openrc errmsg-fix]~> rc-service ${service} status
 * status: stopped

It's kind of a troll to complain to the user about invalid permissions, misleading them to retry with root only to then tell them the service is already stopped - which we could've known without needing root perm as shown in the status call.

i think we can just check if *state == desired_state on the != EWOULDBLOCK case -- will try out something in a moment

maybe i'd be nice to see if there's a proper error for permission as well, and check that, so that other errors don't get mixed with "we have no perms but it's stopped so print 'already stopped'"

@N-R-K
Copy link
Contributor Author

N-R-K commented Feb 12, 2026

Is there a reason not to just do this? Seems clean:

@@ -795,6 +795,11 @@ svc_stop_check(RC_SERVICE *state)
        if (in_background && !(*state & (RC_SERVICE_STARTED | RC_SERVICE_INACTIVE)))
                exit(EXIT_FAILURE);
 
+       if (*state & RC_SERVICE_STOPPED) {
+               ewarn("WARNING: %s is already stopped", applet);
+               return 1;
+       }
+
        if (exclusive_fd == -1)
                exclusive_fd = svc_lock(applet, !deps);
        if (exclusive_fd == -1) {
@@ -806,11 +811,6 @@ svc_stop_check(RC_SERVICE *state)
        }
        fcntl(exclusive_fd, F_SETFD, fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC);
 
-       if (*state & RC_SERVICE_STOPPED) {
-               ewarn("WARNING: %s is already stopped", applet);
-               return 1;
-       }
-
        rc_service_mark(applet, RC_SERVICE_STOPPING);

@navi-desu
Copy link
Member

Is there a reason not to just do this? Seems clean:

@@ -795,6 +795,11 @@ svc_stop_check(RC_SERVICE *state)
        if (in_background && !(*state & (RC_SERVICE_STARTED | RC_SERVICE_INACTIVE)))
                exit(EXIT_FAILURE);
 
+       if (*state & RC_SERVICE_STOPPED) {
+               ewarn("WARNING: %s is already stopped", applet);
+               return 1;
+       }
+
        if (exclusive_fd == -1)
                exclusive_fd = svc_lock(applet, !deps);
        if (exclusive_fd == -1) {
@@ -806,11 +811,6 @@ svc_stop_check(RC_SERVICE *state)
        }
        fcntl(exclusive_fd, F_SETFD, fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC);
 
-       if (*state & RC_SERVICE_STOPPED) {
-               ewarn("WARNING: %s is already stopped", applet);
-               return 1;
-       }
-
        rc_service_mark(applet, RC_SERVICE_STOPPING);

the only issue i see really is a possible race, if another process is either STOPPED > STARTING or STOPPING > STOPPED, realistically either case would basically make it throw a wrong error, by checking state without having a lock

however we're already checking for FAILED/STARTED/INACTIVE before getting the lock anyway, so we might as well just do this

currently trying to stop a service as non-root prints:

    * ERROR: ${service} stopped by something else

but this is plain wrong, the service isn't stopped and the real
reason for failure is due to permission problem. same issue with
starting a service.
otherwise running as non-root will print permission error,
misleading the user to retry with root only to then tell them
the service is already stopped - which we could've known without
needing root perm.
@N-R-K
Copy link
Contributor Author

N-R-K commented Feb 12, 2026

however we're already checking for FAILED/STARTED/INACTIVE before getting the lock anyway, so we might as well just do this

My thought as well. And also, the state variable never gets updated after acquiring the lock either, so doing it after wasn't really solving the race anyways.

@navi-desu navi-desu merged commit f0808ce into OpenRC:master Feb 12, 2026
5 of 7 checks passed
@navi-desu
Copy link
Member

thanks!

@N-R-K N-R-K deleted the errmsg-fix branch February 12, 2026 21:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants