Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recommend merge with xpra-backend #987

Open
wants to merge 10 commits into
base: xpra-backend
Choose a base branch
from
Open
8 changes: 4 additions & 4 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ AM_CPPFLAGS = ${regular_CPPFLAGS} \
-DCONF_XORG='"$(bumblebeedconfdir)/xorg.conf.DRIVER"' \
-DCONF_XORG_DIR='"$(bumblebeedconfdir)/xorg.conf.d"'
AM_CFLAGS = ${regular_CFLAGS} \
${x11_CFLAGS} ${libbsd_CFLAGS} ${glib_CFLAGS} \
${x11_CFLAGS} ${libbsd_CFLAGS} ${glib_CFLAGS} ${kmod_CFLAGS} \
-Wextra -funsigned-char -DGITVERSION='"${GITVERSION}"'

noinst_SCRIPTS = scripts/systemd/bumblebeed.service \
Expand Down Expand Up @@ -49,13 +49,13 @@ sbin_PROGRAMS = bin/bumblebeed
bin_PROGRAMS = bin/optirun

bin_optirun_SOURCES = src/module.c src/bbconfig.c src/bblogger.c src/bbrun.c \
src/bbsocket.c src/driver.c src/optirun.c src/bbsocketclient.c
bin_optirun_LDADD = ${glib_LIBS} -lrt
src/bbsocket.c src/optirun.c src/bbsocketclient.c
bin_optirun_LDADD = ${glib_LIBS} ${kmod_LIBS} -lrt
bin_bumblebeed_SOURCES = src/pci.c src/bbconfig.c src/bblogger.c src/bbrun.c \
src/bbsocket.c src/module.c src/bbsecondary.c src/switch/switching.c \
src/switch/sw_bbswitch.c src/switch/sw_switcheroo.c \
src/driver.c src/bumblebeed.c
bin_bumblebeed_LDADD = ${x11_LIBS} ${libbsd_LIBS} ${glib_LIBS} -lrt
bin_bumblebeed_LDADD = ${x11_LIBS} ${libbsd_LIBS} ${glib_LIBS} ${kmod_LIBS} -lrt

dist_doc_DATA = $(relnotes) README.markdown
bumblebeedconf_DATA = conf/bumblebee.conf conf/xorg.conf.nouveau conf/xorg.conf.nvidia
Expand Down
1 change: 1 addition & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The following packages are dependencies for the build process:
- pkg-config
- glib-2.0 and development headers
- libx11 and development headers
- libkmod2 and development headers
- libbsd and development headers (if pidfile support is enabled, default yes)
- help2man (optional, it is needed for building manual pages)

Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ AC_SUBST([regular_CFLAGS])
# Checks for header files.
PKG_CHECK_MODULES([x11], [x11])
PKG_CHECK_MODULES([glib], [glib-2.0])
PKG_CHECK_MODULES([kmod], [libkmod])
AS_IF([test "x$with_pidfile" != xno], [
PKG_CHECK_MODULES([libbsd], [libbsd >= 0.2.0])
PKG_CHECK_EXISTS([libbsd = 0.2.0], [AC_DEFINE(HAVE_LIBBSD_020)])
Expand Down
12 changes: 6 additions & 6 deletions src/bbconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,6 @@ Bumblebee homepage: <http://Bumblebee-Project.org/>\n", out);
*/
static int bbconfig_parse_common(int opt, char *value) {
switch (opt) {
case 'q'://quiet mode
bb_status.verbosity = VERB_NONE;
break;
case OPT_DEBUG://debug mode
bb_status.verbosity = VERB_ALL;
break;
case 'd'://X display number
set_string_value(&bb_config.x_display, value);
break;
Expand Down Expand Up @@ -307,6 +301,12 @@ void bbconfig_parse_opts(int argc, char *argv[], int conf_round) {
bb_status.verbosity++;
}
break;
case 'q'://quiet mode
bb_status.verbosity = VERB_NONE;
break;
case OPT_DEBUG://debug mode
bb_status.verbosity = VERB_ALL;
break;
case 's': /* Unix socket to use for communication */
set_string_value(&bb_config.socket_path, optarg);
break;
Expand Down
2 changes: 2 additions & 0 deletions src/bbconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <unistd.h> //for pid_t
#include <limits.h> //for CHAR_MAX
#include <glib.h>
#include <libkmod.h>

/* Daemon states */
#define BB_DAEMON 1
Expand Down Expand Up @@ -118,6 +119,7 @@ struct bb_status_struct {
int x_pipe[2];//pipes for reading/writing output from X's stdout/stderr
gboolean use_syslog;
char *program_name;
struct kmod_ctx *kmod_ctx;
};

/* Structure containing the configuration. */
Expand Down
4 changes: 2 additions & 2 deletions src/bblogger.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ void check_xorg_pipe(void){
/* line / buffer is full, process the remaining buffer the next round */
repeat = 1;
}
}else{
} else {
if (r == 0 || (errno != EAGAIN && r == -1)){
/* the pipe is closed/invalid. Clean up. */
if (bb_status.x_pipe[0] != -1){close(bb_status.x_pipe[0]); bb_status.x_pipe[0] = -1;}
Expand Down Expand Up @@ -254,5 +254,5 @@ void check_xorg_pipe(void){
memmove(x_output_buffer, next_part, x_buffer_pos);
}
}
}while(repeat);
}while (repeat);
}/* check_xorg_pipe */
12 changes: 12 additions & 0 deletions src/bumblebeed.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <libkmod.h>
#ifdef WITH_PIDFILE
#ifdef HAVE_LIBBSD_020
#include <libutil.h>
Expand Down Expand Up @@ -488,6 +489,14 @@ int main(int argc, char* argv[]) {

free(pci_id_igd);

// kmod context have to be available for driver detection
bb_status.kmod_ctx = kmod_new(NULL, NULL);
if (bb_status.kmod_ctx == NULL) {
bb_log(LOG_ERR, "kmod_new() failed!\n");
bb_closelog();
exit(EXIT_FAILURE);
}

GKeyFile *bbcfg = bbconfig_parse_conf();
bbconfig_parse_opts(argc, argv, PARSE_STAGE_DRIVER);
driver_detect();
Expand All @@ -500,6 +509,7 @@ int main(int argc, char* argv[]) {

/* dump the config after detecting the driver */
config_dump();

if (config_validate() != 0) {
return (EXIT_FAILURE);
}
Expand Down Expand Up @@ -572,5 +582,7 @@ int main(int argc, char* argv[]) {
//close X pipe, if any parts of it are open still
if (bb_status.x_pipe[0] != -1){close(bb_status.x_pipe[0]); bb_status.x_pipe[0] = -1;}
if (bb_status.x_pipe[1] != -1){close(bb_status.x_pipe[1]); bb_status.x_pipe[1] = -1;}
//cleanup kmod context
kmod_unref(bb_status.kmod_ctx);
return (EXIT_SUCCESS);
}
186 changes: 125 additions & 61 deletions src/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,90 +24,152 @@
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <libkmod.h>
#include <errno.h>
#include "module.h"
#include "bblogger.h"
#include "bbrun.h"
#include "bbconfig.h"

int module_unload_recursive(struct kmod_module *mod);

/**
* Checks in /proc/modules whether a kernel module is loaded
* Checks whether a kernel module is loaded
*
* @param driver The name of the driver (not a filename)
* @return 1 if the module is loaded, 0 otherwise
*/
int module_is_loaded(char *driver) {
// use the same buffer length as lsmod
char buffer[4096];
FILE * bbs = fopen("/proc/modules", "r");
int ret = 0;
/* assume mod_len <= sizeof(buffer) */
int mod_len = strlen(driver);

if (bbs == 0) {//error opening, return -1
bb_log(LOG_DEBUG, "Couldn't open /proc/modules");
return -1;
}
while (fgets(buffer, sizeof(buffer), bbs)) {
/* match "module" with "module " and not "module-blah" */
if (!strncmp(buffer, driver, mod_len) && isspace(buffer[mod_len])) {
/* module is found */
ret = 1;
break;
}
int err, state;
struct kmod_module *mod;

err = kmod_module_new_from_name(bb_status.kmod_ctx, driver, &mod);
if (err < 0) {
bb_log(LOG_DEBUG, "kmod_module_new_from_name(%s) failed (err: %d).\n",
driver, err);
return 0;
}
fclose(bbs);
return ret;

state = kmod_module_get_initstate(mod);
kmod_module_unref(mod);

return state == KMOD_MODULE_LIVE;
}

/**
* Attempts to load a module. If the module has not been loaded after ten
* seconds, give up
* Attempts to load a module.
*
* @param module_name The filename of the module to be loaded
* @param driver The name of the driver to be loaded
* @return 1 if the driver is succesfully loaded, 0 otherwise
*/
int module_load(char *module_name, char *driver) {
int err = 0;
int flags = KMOD_PROBE_IGNORE_LOADED;
struct kmod_list *l, *list = NULL;

if (module_is_loaded(driver) == 0) {
/* the module has not loaded yet, try to load it */
bb_log(LOG_INFO, "Loading driver %s (module %s)\n", driver, module_name);
char *mod_argv[] = {
"modprobe",
module_name,
NULL
};
bb_run_fork_wait(mod_argv, 10);
if (module_is_loaded(driver) == 0) {
bb_log(LOG_ERR, "Module %s could not be loaded (timeout?)\n", module_name);

bb_log(LOG_INFO, "Loading driver '%s' (module '%s')\n", driver, module_name);
err = kmod_module_new_from_lookup(bb_status.kmod_ctx, module_name, &list);

if (err < 0) {
bb_log(LOG_DEBUG, "kmod_module_new_from_lookup(%s) failed (err: %d).\n",
module_name, err);
return 0;
}

if (list == NULL) {
bb_log(LOG_ERR, "Module '%s' not found.\n", module_name);
return 0;
}

kmod_list_foreach(l, list) {
struct kmod_module *mod = kmod_module_get_module(l);

bb_log(LOG_DEBUG, "Loading module '%s'.\n", kmod_module_get_name(mod));
err = kmod_module_probe_insert_module(mod, flags, NULL, NULL, NULL, 0);

if (err < 0) {
bb_log(LOG_DEBUG, "kmod_module_probe_insert_module(%s) failed (err: %d).\n",
kmod_module_get_name(mod), err);
}

kmod_module_unref(mod);

if (err < 0) {
break;
}
}

kmod_module_unref_list(list);
}
return 1;

return err >= 0;
}

/**
* Attempts to unload a module if loaded, for ten seconds before
* giving up
* Unloads module and modules that are depending on this module.
*
* @param mod Reference to libkmod module
* @return 1 if the module is succesfully unloaded, 0 otherwise
*/
int module_unload_recursive(struct kmod_module *mod) {
int err = 0, flags = 0, refcnt;
struct kmod_list *holders;

holders = kmod_module_get_holders(mod);
if (holders != NULL) {
struct kmod_list *itr;

kmod_list_foreach(itr, holders) {
struct kmod_module *hm = kmod_module_get_module(itr);
err = module_unload_recursive(hm);
kmod_module_unref(hm);

if (err < 0) {
break;
}
}
kmod_module_unref_list(holders);
}

refcnt = kmod_module_get_refcnt(mod);
if (refcnt == 0) {
bb_log(LOG_INFO, "Unloading module %s\n", kmod_module_get_name(mod));
err = kmod_module_remove_module(mod, flags);
} else {
bb_log(LOG_ERR, "Failed to unload module '%s' (ref count: %d).\n",
kmod_module_get_name(mod), refcnt);
err = 1;
}

return err == 0;
}

/**
* Attempts to unload a module if loaded.
*
* @param driver The name of the driver (not a filename)
* @return 1 if the driver is succesfully unloaded, 0 otherwise
*/
int module_unload(char *driver) {
int err;
struct kmod_module *mod;
if (module_is_loaded(driver) == 1) {
int retries = 30;
bb_log(LOG_INFO, "Unloading %s driver\n", driver);
char *mod_argv[] = {
"rmmod",
driver,
NULL
};
bb_run_fork_wait(mod_argv, 10);
while (retries-- > 0 && module_is_loaded(driver) == 1) {
usleep(100000);
}
if (module_is_loaded(driver) == 1) {
bb_log(LOG_ERR, "Unloading %s driver timed out.\n", driver);
err = kmod_module_new_from_name(bb_status.kmod_ctx, driver, &mod);

if (err < 0) {
bb_log(LOG_DEBUG, "kmod_module_new_from_name(%s) failed (err: %d).\n",
driver, err);
return 0;
}

err = module_unload_recursive(mod);
kmod_module_unref(mod);

return err;
}
return 1;
}
Expand All @@ -119,18 +181,20 @@ int module_unload(char *driver) {
* @return 1 if the module is available for loading, 0 otherwise
*/
int module_is_available(char *module_name) {
/* HACK to support call from optirun */
char *modprobe_bin = "/sbin/modprobe";
if (access(modprobe_bin, X_OK)) {
/* if /sbin/modprobe is not found, pray that PATH contains it */
modprobe_bin = "modprobe";
int err, available;
struct kmod_list *list = NULL;

err = kmod_module_new_from_lookup(bb_status.kmod_ctx, module_name, &list);

if (err < 0) {
bb_log(LOG_DEBUG, "kmod_module_new_from_lookup(%s) failed (err: %d).\n",
module_name, err);
return 0;
}
char *mod_argv[] = {
modprobe_bin,
"--dry-run",
"--quiet",
module_name,
NULL
};
return bb_run_fork(mod_argv, 1) == EXIT_SUCCESS;

available = list != NULL;

kmod_module_unref_list(list);

return available;
}
1 change: 0 additions & 1 deletion src/optirun.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
#include "bbsocketclient.h"
#include "bblogger.h"
#include "bbrun.h"
#include "driver.h"


/**
Expand Down