[RFC] new initctl command

Colin Watson cjwatson at ubuntu.com
Tue Jun 21 09:46:54 UTC 2011


On Tue, Jun 21, 2011 at 10:45:04AM +0300, Surbhi Palande wrote:
> On 06/21/2011 03:19 AM, Colin Watson wrote:
> >On IRC a few days ago, I suggested using a D-Bus signal (not to be
> >confused with Unix signals, of course), so that initctl doesn't have to
> >wait for a reply from init and you don't need this awkward pair of
> >processes.  You said today that that had proved to be difficult because
> >there was no implementation that let you send a signal to upstart from
> >initctl.  Could you explain in more detail why this didn't work out?
> 
> Actually, I have not tried this in detail. But when I looked at the
> xml files and the implementations of the signals, it turned out that
> all the signals were sent *from* upstart and none to upstart.
> 
> So for example, if I do this:
> 
>     <signal name="PivotToNewRootfs">
>       <arg name="rootfs" type="s" direction="in"/>
>       <arg name="init" type="s"  direction="in"/>
>     </signal>
> 
> then the compiler complains that the direction cannot be "in" but
> has to be "out". I comprehended this as upstart sending the
> arguments "out" to the outside world. I don't know the current
> method of making the direction of the arguments "in" to upstart. Is
> there a simple way of doing this? I am missing something there :-/

Ah, yes, of course the signal would have to be declared on a
non-existent initctl interface rather than on the main upstart control
interface for that to work.  That's probably too much like hard work.
Shame.

However, now that I've refreshed my memory about the protocol, there's a
way to send a D-Bus method call without bothering to wait for the reply.
Try something like this, with PivotToNewRootfs declared as a method
again:

  DBusPendingCall *       pending_call;

  /* ... body of pivot_action ... */

  pending_call = upstart_pivot_to_new_rootfs (upstart, args[0], args[1],
                                              NULL, NULL, NULL, 0);
  if (! pending_call) {
          err = nih_error_get ();
          nih_error ("%s", err->message);
          nih_free (err);
  }
  return 0;


The important bits are that you aren't using the _sync variant, and that
the fifth argument (error_handler) is NULL.  If you look at the
implementation, this takes you into this path:

        /* Handle a fire-and-forget message */
        if (! error_handler) {
                dbus_message_set_no_reply (method_call, TRUE);
                if (! dbus_connection_send (proxy->connection, method_call, NULL)) {
                        dbus_message_unref (method_call);
                        nih_return_no_memory_error (NULL);
                }

                dbus_message_unref (method_call);
                return (DBusPendingCall *)TRUE;
        }

That looks like what you want: tell D-Bus you don't care about a reply
(equivalent to omitting --print-reply in a dbus-send command, for
instance), send the marshalled method call out over the wire, and then
return immediately.

-- 
Colin Watson                                       [cjwatson at ubuntu.com]



More information about the upstart-devel mailing list