$darkmode
Elektra 0.11.0
Functions
pluginprocess.c File Reference

Source for the pluginprocess library. More...

#include "kdbpluginprocess.h"
#include <kdberrors.h>
#include <kdbinvoke.h>
#include <kdblogger.h>
#include <kdbprivate.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
Include dependency graph for pluginprocess.c:

Functions

void elektraPluginProcessStart (Plugin *handle, ElektraPluginProcess *pp)
 Start the child process' command loop. More...
 
int elektraPluginProcessSend (const ElektraPluginProcess *pp, pluginprocess_t command, KeySet *originalKeySet, Key *key)
 Call a plugin's function in a child process. More...
 
int elektraPluginProcessIsParent (const ElektraPluginProcess *pp)
 Check if a given plugin process is the parent or the child process. More...
 
ElektraPluginProcess * elektraPluginProcessInit (Key *errorKey)
 Initialize a plugin to be executed in its own process. More...
 
int elektraPluginProcessOpen (ElektraPluginProcess *pp, Key *errorKey)
 Call a plugin's open function in a child process. More...
 
ElektraPluginProcessCloseResult elektraPluginProcessClose (ElektraPluginProcess *pp, Key *errorKey)
 Cleanup a plugin process. More...
 
void elektraPluginProcessSetData (ElektraPluginProcess *pp, void *data)
 Store a pointer to any plugin related data that is being executed inside an own process. More...
 
void * elektraPluginProcessGetData (const ElektraPluginProcess *pp)
 Get a pointer to any plugin related data stored before. More...
 

Detailed Description

Source for the pluginprocess library.

Executes plugins in a separate process via fork and uses a simple communication protocol based on the dump plugin via named pipes.

The communication protocol works as follows, where Child and Parent stand for the child and the parent process: 1) Four pipes are created to handle the communication in a reliable way

Function Documentation

◆ elektraPluginProcessClose()

ElektraPluginProcessCloseResult elektraPluginProcessClose ( ElektraPluginProcess *  pp,
Key *  errorKey 
)

Cleanup a plugin process.

This will decrease the internal counter how often open/close has been called, closing opened pipes when the counter reaches 0. This will not delete the plugin data associated with the handle as it may contain other data out of the scope of this library, so this has to be done manually like

int elektraPluginClose (Plugin * handle, Key * errorKey)
{
ElektraPluginProcess * pp = elektraPluginGetData (handle);
if (pp && elektraPluginProcessIsParent (pp)) {
ElektraPluginProcessCloseResult result = elektraPluginProcessClose (pp, errorKey);
if (result.cleanedUp) elektraPluginSetData (handle, NULL);
return result.result;
}
// actual plugin functionality to be executed in a child process
}
void * elektraPluginGetData(Plugin *plugin)
Get a pointer to the plugin specific data stored before.
Definition: plugin/plugin.c:150
void elektraPluginSetData(Plugin *plugin, void *data)
Store a pointer to plugin specific data.
Definition: plugin/plugin.c:133
#define ELEKTRA_PLUGIN_STATUS_SUCCESS
Everything went fine.
Definition: kdbplugin.h:86
ElektraPluginProcessCloseResult elektraPluginProcessClose(ElektraPluginProcess *pp, Key *errorKey)
Cleanup a plugin process.
Definition: pluginprocess.c:585
int elektraPluginProcessIsParent(const ElektraPluginProcess *pp)
Check if a given plugin process is the parent or the child process.
Definition: pluginprocess.c:395

Note that pp might be null here if the initialization failed!

Parameters
ppthe data structure containing the plugin's process information
Return values
1if the data structure got cleaned up
0if the data structure is still used

◆ elektraPluginProcessGetData()

void* elektraPluginProcessGetData ( const ElektraPluginProcess *  pp)

Get a pointer to any plugin related data stored before.

If elektraPluginProcessSetData was not called earlier, NULL will be returned.

Parameters
ppthe data structure containing the plugin's process information
Return values
apointer to the data

◆ elektraPluginProcessInit()

ElektraPluginProcess* elektraPluginProcessInit ( Key *  errorKey)

Initialize a plugin to be executed in its own process.

This will prepare all the required resources and then fork the current process. After the initialization the child process will typically call the command loop while the parent starts to send commands to it. Also the resulting process information has to be stored for the plugin. In order to allow users to handle custom plugin data this will not automatically call elektraPluginSetData.

Typically called in a plugin's open function like (assuming no custom plugin data):

int elektraPluginOpen (Plugin * handle, Key * errorKey)
{
ElektraPluginProcess * pp = elektraPluginGetData (handle);
if (pp == NULL)
{
if ((pp = elektraPluginProcessInit (errorKey)) == NULL) return ELEKTRA_PLUGIN_STATUS_ERROR;
elektraPluginSetData (handle, pp);
}
if (elektraPluginProcessIsParent (pp)) return elektraPluginProcessOpen (pp, errorKey);
// actual plugin functionality to be executed in a child process
}
Plugin * elektraPluginOpen(const char *name, KeySet *modules, KeySet *config, Key *errorKey)
Opens a plugin.
Definition: elektra/plugin.c:47
#define ELEKTRA_PLUGIN_STATUS_ERROR
An error occurred inside the plugin function.
Definition: kdbplugin.h:83
void elektraPluginProcessStart(Plugin *handle, ElektraPluginProcess *pp)
Start the child process' command loop.
Definition: pluginprocess.c:127
int elektraPluginProcessOpen(ElektraPluginProcess *pp, Key *errorKey)
Call a plugin's open function in a child process.
Definition: pluginprocess.c:551
ElektraPluginProcess * elektraPluginProcessInit(Key *errorKey)
Initialize a plugin to be executed in its own process.
Definition: pluginprocess.c:471
Parameters
handlethe plugin's handle
errorKeya key where error messages will be set
Return values
NULLif the initialization failed
apointer to the information

◆ elektraPluginProcessIsParent()

int elektraPluginProcessIsParent ( const ElektraPluginProcess *  pp)

Check if a given plugin process is the parent or the child process.

Parameters
ppthe data structure containing the plugin's process information
Return values
0if it's the child process
thechild process' pid otherwise

◆ elektraPluginProcessOpen()

int elektraPluginProcessOpen ( ElektraPluginProcess *  pp,
Key *  errorKey 
)

Call a plugin's open function in a child process.

This will increase the internal counter how often open/close has been called, so the opened pipes and forks will not be closed too early.

Parameters
ppthe data structure containing the plugin's process information
errorKeya key where error messages will be set
Return values
thereturn value of the plugin's open function
See also
elektraPluginProcessInit for an example how and where this function is typically used

◆ elektraPluginProcessSend()

int elektraPluginProcessSend ( const ElektraPluginProcess *  pp,
pluginprocess_t  command,
KeySet *  originalKeySet,
Key *  key 
)

Call a plugin's function in a child process.

This will wrap all the required information to execute the given command in a keyset and send it over to the child process. Then it waits for the child process's answer and copies the result back into the original plugin keyset and plugin key.

Typically called like

int elektraPluginSet (Plugin * handle, KeySet * returned, Key * parentKey)
{
ElektraPluginProcess * pp = elektraPluginGetData (handle);
if (elektraPluginProcessIsParent (pp)) return elektraPluginProcessSend (pp, ELEKTRA_PLUGINPROCESS_SET, returned, parentKey);
// actual plugin functionality to be executed in a child process
}
int elektraPluginProcessSend(const ElektraPluginProcess *pp, pluginprocess_t command, KeySet *originalKeySet, Key *key)
Call a plugin's function in a child process.
Definition: pluginprocess.c:268
Parameters
ppthe data structure containing the plugin's process information
commandthe plugin command that should be executed, e.g. ELEKTRA_PLUGINPROCESS_GET
originalKeySetthe original key set that the parent process receives
keythe original key the parent process receives
Return values
ELEKTRA_PLUGIN_STATUS_ERRORif the child process communication failed
thecalled plugin's return value otherwise
See also
elektraPluginProcessIsParent for checking if we are in the parent or child process

◆ elektraPluginProcessSetData()

void elektraPluginProcessSetData ( ElektraPluginProcess *  pp,
void *  data 
)

Store a pointer to any plugin related data that is being executed inside an own process.

This is required in case additional arbitrary plugin data should be stored. Pluginprocess has to be stored using elektraPluginSetData. Plugin data for the child process has to be stored using this function like

int elektraPluginOpen (Plugin * handle, Key * errorKey)
{
ElektraPluginProcess * pp = elektraPluginGetData (handle);
if (pp == NULL)
{
if ((pp = elektraPluginProcessInit (errorKey)) == NULL) return ELEKTRA_PLUGIN_STATUS_ERROR;
ArbitraryPluginData * data = // initialize your plugin data
elektraPluginSetData (handle, pp);
}
if (elektraPluginProcessIsParent (pp)) return elektraPluginProcessOpen (pp, errorKey);
// actual plugin functionality to be executed in a child process
}
void elektraPluginProcessSetData(ElektraPluginProcess *pp, void *data)
Store a pointer to any plugin related data that is being executed inside an own process.
Definition: pluginprocess.c:650

Furthermore ensure to cleanup the data after the plugin is done like

int elektraPluginClose (Plugin * handle, Key * errorKey)
{
ElektraPluginProcess * pp = elektraPluginGetData (handle);
ArbitraryPluginData * data = elektraPluginProcessGetData (pp);
ElektraPluginProcessCloseResult result = elektraPluginProcessClose (pp, errorKey);
if (result.cleanedUp)
{
elektraPluginSetData (handle, NULL);
// cleanup data here, this was the last call to the plugin
}
return result.result;
}
// actual plugin functionality to be executed in a child process
}
void * elektraPluginProcessGetData(const ElektraPluginProcess *pp)
Get a pointer to any plugin related data stored before.
Definition: pluginprocess.c:662

This way you can use elektraPluginProcessGetData (handle) in your child process to get the data you want your plugin to work with.

Parameters
ppthe data structure containing the plugin's process information
datathe pointer to the data

◆ elektraPluginProcessStart()

void elektraPluginProcessStart ( Plugin *  handle,
ElektraPluginProcess *  pp 
)

Start the child process' command loop.

This will make the child process wait for plugin commands and execute them, returning the result to the parent. This is typically called in a plugin's open function.

Parameters
handlethe plugin's handle
ppthe data structure containing the plugin's process information
See also
elektraPluginProcessInit how to use this function in a Plugins