jack1 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

565 lines
13KB

  1. /* -*- mode: c; c-file-style: "bsd"; -*- */
  2. /*
  3. Copyright (C) 2001-2003 Paul Davis
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. $Id$
  16. */
  17. #include <stdio.h>
  18. #include <signal.h>
  19. #include <getopt.h>
  20. #include <sys/types.h>
  21. #include <sys/shm.h>
  22. #include <sys/wait.h>
  23. #include <string.h>
  24. #include <errno.h>
  25. #include <stdlib.h>
  26. #include <dirent.h>
  27. #include <dlfcn.h>
  28. #include <config.h>
  29. #include <jack/engine.h>
  30. #include <jack/internal.h>
  31. #include <jack/driver.h>
  32. #include <jack/shm.h>
  33. #include <jack/driver_parse.h>
  34. #ifdef USE_CAPABILITIES
  35. #include <sys/stat.h>
  36. /* capgetp and capsetp are linux only extensions, not posix */
  37. #undef _POSIX_SOURCE
  38. #include <sys/capability.h>
  39. #include <jack/start.h>
  40. static struct stat pipe_stat;
  41. #endif
  42. static JSList * drivers = NULL;
  43. static sigset_t signals;
  44. static jack_engine_t *engine = 0;
  45. static int realtime = 0;
  46. static int realtime_priority = 10;
  47. static int verbose = 0;
  48. static int asio_mode = 0;
  49. static int client_timeout = 500; /* msecs */
  50. static void
  51. do_nothing_handler (int sig)
  52. {
  53. /* this is used by the child (active) process, but it never
  54. gets called unless we are already shutting down after
  55. another signal.
  56. */
  57. char buf[64];
  58. snprintf (buf, sizeof(buf),
  59. "received signal %d during shutdown (ignored)\n", sig);
  60. write (1, buf, strlen (buf));
  61. }
  62. static int
  63. jack_main (jack_driver_desc_t * driver_desc, JSList * driver_params)
  64. {
  65. int sig;
  66. int i;
  67. sigset_t allsignals;
  68. struct sigaction action;
  69. int waiting;
  70. /* ensure that we are in our own process group so that
  71. kill (SIG, -pgrp) does the right thing.
  72. */
  73. setsid ();
  74. pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  75. /* what's this for?
  76. POSIX says that signals are delivered like this:
  77. * if a thread has blocked that signal, it is not
  78. a candidate to receive the signal.
  79. * of all threads not blocking the signal, pick
  80. one at random, and deliver the signal.
  81. this means that a simple-minded multi-threaded program can
  82. expect to get POSIX signals delivered randomly to any one
  83. of its threads,
  84. here, we block all signals that we think we might receive
  85. and want to catch. all "child" threads will inherit this
  86. setting. if we create a thread that calls sigwait() on the
  87. same set of signals, implicitly unblocking all those
  88. signals. any of those signals that are delivered to the
  89. process will be delivered to that thread, and that thread
  90. alone. this makes cleanup for a signal-driven exit much
  91. easier, since we know which thread is doing it and more
  92. importantly, we are free to call async-unsafe functions,
  93. because the code is executing in normal thread context
  94. after a return from sigwait().
  95. */
  96. sigemptyset (&signals);
  97. sigaddset(&signals, SIGHUP);
  98. sigaddset(&signals, SIGINT);
  99. sigaddset(&signals, SIGQUIT);
  100. sigaddset(&signals, SIGPIPE);
  101. sigaddset(&signals, SIGTERM);
  102. sigaddset(&signals, SIGUSR1);
  103. sigaddset(&signals, SIGUSR2);
  104. /* all child threads will inherit this mask unless they
  105. * explicitly reset it
  106. */
  107. pthread_sigmask (SIG_BLOCK, &signals, 0);
  108. /* get the engine/driver started */
  109. if ((engine = jack_engine_new (realtime, realtime_priority,
  110. verbose, client_timeout,
  111. getpid(), drivers)) == 0) {
  112. fprintf (stderr, "cannot create engine\n");
  113. return -1;
  114. }
  115. fprintf (stderr, "loading driver ..\n");
  116. if (jack_engine_load_driver (engine, driver_desc, driver_params)) {
  117. fprintf (stderr, "cannot load driver module %s\n", driver_desc->name);
  118. return -1;
  119. }
  120. if (asio_mode) {
  121. jack_set_asio_mode (engine, TRUE);
  122. }
  123. if (engine->driver->start (engine->driver) != 0) {
  124. jack_error ("cannot start driver");
  125. return -1;
  126. }
  127. /* install a do-nothing handler because otherwise pthreads
  128. behaviour is undefined when we enter sigwait.
  129. */
  130. sigfillset (&allsignals);
  131. action.sa_handler = do_nothing_handler;
  132. action.sa_mask = allsignals;
  133. action.sa_flags = SA_RESTART|SA_RESETHAND;
  134. for (i = 1; i < NSIG; i++) {
  135. if (sigismember (&signals, i)) {
  136. sigaction (i, &action, 0);
  137. }
  138. }
  139. if (verbose) {
  140. fprintf (stderr, "%d waiting for signals\n", getpid());
  141. }
  142. waiting = TRUE;
  143. while (waiting) {
  144. sigwait (&signals, &sig);
  145. fprintf (stderr, "jack main caught signal %d\n", sig);
  146. switch (sig) {
  147. case SIGUSR1:
  148. jack_dump_configuration(engine, 1);
  149. break;
  150. case SIGUSR2:
  151. /* driver exit */
  152. waiting = FALSE;
  153. break;
  154. default:
  155. waiting = FALSE;
  156. break;
  157. }
  158. }
  159. if (sig != SIGSEGV) {
  160. /* unblock signals so we can see them during shutdown.
  161. this will help prod developers not to lose sight of
  162. bugs that cause segfaults etc. during shutdown.
  163. */
  164. sigprocmask (SIG_UNBLOCK, &signals, 0);
  165. }
  166. jack_engine_delete (engine);
  167. return 1;
  168. }
  169. static jack_driver_desc_t *
  170. jack_drivers_get_descriptor (JSList * drivers, const char * sofile)
  171. {
  172. jack_driver_desc_t * descriptor, * other_descriptor;
  173. JackDriverDescFunction so_get_descriptor;
  174. JSList * node;
  175. void * dlhandle;
  176. char * filename;
  177. const char * dlerr;
  178. int err;
  179. filename = malloc (strlen (ADDON_DIR) + 1 + strlen (sofile) + 1);
  180. sprintf (filename, "%s/%s", ADDON_DIR, sofile);
  181. if (verbose)
  182. printf ("getting driver descriptor from %s\n", filename);
  183. dlhandle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
  184. if (!dlhandle) {
  185. jack_error ("could not open driver .so '%s': %s\n", filename, dlerror ());
  186. free (filename);
  187. return NULL;
  188. }
  189. dlerror ();
  190. so_get_descriptor = (JackDriverDescFunction)
  191. dlsym (dlhandle, "driver_get_descriptor");
  192. dlerr = dlerror ();
  193. if (dlerr) {
  194. dlclose (dlhandle);
  195. free (filename);
  196. return NULL;
  197. }
  198. descriptor = so_get_descriptor ();
  199. if (!descriptor) {
  200. jack_error ("driver from '%s' returned NULL descriptor\n", filename);
  201. dlclose (dlhandle);
  202. free (filename);
  203. return NULL;
  204. }
  205. err = dlclose (dlhandle);
  206. if (err) {
  207. jack_error ("error closing driver .so '%s': %s\n", filename, dlerror ());
  208. }
  209. /* check it doesn't exist already */
  210. for (node = drivers; node; node = jack_slist_next (node)) {
  211. other_descriptor = (jack_driver_desc_t *) node->data;
  212. if (strcmp (descriptor->name, other_descriptor->name) == 0) {
  213. jack_error ("the drivers in '%s' and '%s' both have the name '%s'; using the first\n",
  214. other_descriptor->file, filename, other_descriptor->name);
  215. /* FIXME: delete the descriptor */
  216. free (filename);
  217. return NULL;
  218. }
  219. }
  220. strncpy (descriptor->file, filename, PATH_MAX);
  221. free (filename);
  222. return descriptor;
  223. }
  224. static JSList *
  225. jack_drivers_load ()
  226. {
  227. struct dirent * dir_entry;
  228. DIR * dir_stream;
  229. const char * ptr;
  230. int err;
  231. JSList * driver_list = NULL;
  232. jack_driver_desc_t * desc;
  233. /* search through the ADDON_DIR and add get descriptors
  234. from the .so files in it */
  235. dir_stream = opendir (ADDON_DIR);
  236. if (!dir_stream) {
  237. jack_error ("could not open driver directory %s: %s\n", ADDON_DIR, strerror (errno));
  238. return NULL;
  239. }
  240. while ( (dir_entry = readdir (dir_stream)) ) {
  241. /* check the filename is of the right format */
  242. if (strncmp ("jack_", dir_entry->d_name, 5) != 0) {
  243. continue;
  244. }
  245. ptr = strrchr (dir_entry->d_name, '.');
  246. if (!ptr) {
  247. continue;
  248. }
  249. ptr++;
  250. if (strncmp ("so", ptr, 2) != 0) {
  251. continue;
  252. }
  253. desc = jack_drivers_get_descriptor (drivers, dir_entry->d_name);
  254. if (desc) {
  255. driver_list = jack_slist_append (driver_list, desc);
  256. }
  257. }
  258. err = closedir (dir_stream);
  259. if (err) {
  260. jack_error ("error closing driver directory %s: %s\n", ADDON_DIR, strerror (errno));
  261. }
  262. if (!driver_list) {
  263. jack_error ("could not find any drivers in %s!\n", ADDON_DIR);
  264. return NULL;
  265. }
  266. return driver_list;
  267. }
  268. static void copyright (FILE* file)
  269. {
  270. fprintf (file, "jackd " VERSION "\n"
  271. "Copyright 2001-2003 Paul Davis and others.\n"
  272. "jackd comes with ABSOLUTELY NO WARRANTY\n"
  273. "This is free software, and you are welcome to redistribute it\n"
  274. "under certain conditions; see the file COPYING for details\n\n");
  275. }
  276. static void usage (FILE *file)
  277. {
  278. copyright (file);
  279. fprintf (file, "\n"
  280. "usage: jackd [ --asio OR -a ]\n"
  281. " [ --realtime OR -R [ --realtime-priority OR -P priority ] ]\n"
  282. " [ --timeout OR -t client-timeout-in-msecs ]\n"
  283. " [ --verbose OR -v ]\n"
  284. " [ --silent OR -s ]\n"
  285. " [ --tmpdir OR -D directory-for-temporary-files ]\n"
  286. " [ --version OR -V ]\n"
  287. " -d driver [ ... driver args ... ]\n");
  288. }
  289. static jack_driver_desc_t *
  290. jack_find_driver_descriptor (const char * name)
  291. {
  292. jack_driver_desc_t * desc;
  293. JSList * node;
  294. for (node = drivers; node; node = jack_slist_next (node)) {
  295. desc = (jack_driver_desc_t *) node->data;
  296. if (strcmp (desc->name, name) != 0) {
  297. desc = NULL;
  298. } else {
  299. break;
  300. }
  301. }
  302. return desc;
  303. }
  304. int
  305. main (int argc, char *argv[])
  306. {
  307. jack_driver_desc_t * desc;
  308. const char *options = "-ad:D:P:vshVRFl:t:";
  309. struct option long_options[] =
  310. {
  311. { "asio", 0, 0, 'a' },
  312. { "driver", 1, 0, 'd' },
  313. { "tmpdir", 1, 0, 'D' },
  314. { "verbose", 0, 0, 'v' },
  315. { "help", 0, 0, 'h' },
  316. { "realtime", 0, 0, 'R' },
  317. { "realtime-priority", 1, 0, 'P' },
  318. { "timeout", 1, 0, 't' },
  319. { "version", 0, 0, 'V' },
  320. { "silent", 0, 0, 's' },
  321. { 0, 0, 0, 0 }
  322. };
  323. int option_index;
  324. int opt;
  325. int seen_driver = 0;
  326. char *driver_name = 0;
  327. char **driver_args = 0;
  328. JSList * driver_params;
  329. int driver_nargs = 1;
  330. int show_version = 0;
  331. int i;
  332. #ifdef USE_CAPABILITIES
  333. int status;
  334. #endif
  335. setvbuf (stdout, NULL, _IOLBF, 120);
  336. #ifdef USE_CAPABILITIES
  337. /* check to see if there is a pipe in the right descriptor */
  338. if ((status = fstat (PIPE_WRITE_FD, &pipe_stat)) == 0 &&
  339. S_ISFIFO(pipe_stat.st_mode)) {
  340. /* tell jackstart we are up and running */
  341. char c = 1;
  342. if (write (PIPE_WRITE_FD, &c, 1) != 1) {
  343. fprintf (stderr, "cannot write to jackstart sync "
  344. "pipe %d (%s)\n", PIPE_WRITE_FD,
  345. strerror (errno));
  346. }
  347. if (close(PIPE_WRITE_FD) != 0) {
  348. fprintf(stderr,
  349. "jackd: error on startup pipe close: %s\n",
  350. strerror (errno));
  351. } else {
  352. /* wait for jackstart process to set our capabilities */
  353. if (wait (&status) == -1) {
  354. fprintf (stderr, "jackd: wait for startup "
  355. "process exit failed\n");
  356. }
  357. if (!WIFEXITED (status) || WEXITSTATUS (status)) {
  358. fprintf(stderr, "jackd: jackstart did not "
  359. "exit cleanly\n");
  360. exit (1);
  361. }
  362. }
  363. }
  364. #endif
  365. opterr = 0;
  366. while (!seen_driver && (opt = getopt_long (argc, argv, options,
  367. long_options,
  368. &option_index)) != EOF) {
  369. switch (opt) {
  370. case 'a':
  371. asio_mode = TRUE;
  372. break;
  373. case 'D':
  374. jack_set_server_dir (optarg);
  375. break;
  376. case 'd':
  377. seen_driver = 1;
  378. driver_name = optarg;
  379. break;
  380. case 'v':
  381. verbose = 1;
  382. break;
  383. case 's':
  384. jack_set_error_function (silent_jack_error_callback);
  385. break;
  386. case 'P':
  387. realtime_priority = atoi (optarg);
  388. break;
  389. case 'R':
  390. realtime = 1;
  391. break;
  392. case 't':
  393. client_timeout = atoi (optarg);
  394. break;
  395. case 'V':
  396. show_version = 1;
  397. break;
  398. default:
  399. fprintf (stderr, "unknown option character %c\n",
  400. optopt);
  401. /*fallthru*/
  402. case 'h':
  403. usage (stdout);
  404. return -1;
  405. }
  406. }
  407. if (show_version) {
  408. printf ( "jackd version " VERSION "\n");
  409. #ifdef DEFAULT_TMP_DIR
  410. printf ( "default tmp directory: " DEFAULT_TMP_DIR "\n");
  411. #else
  412. printf ( "default tmp directory: /tmp\n");
  413. #endif
  414. return -1;
  415. }
  416. if (!seen_driver) {
  417. usage (stderr);
  418. exit (1);
  419. }
  420. drivers = jack_drivers_load ();
  421. if (!drivers)
  422. {
  423. fprintf (stderr, "jackd: no drivers found; exiting\n");
  424. exit (1);
  425. }
  426. desc = jack_find_driver_descriptor (driver_name);
  427. if (!desc)
  428. {
  429. fprintf (stderr, "jackd: unknown driver '%s'\n", driver_name);
  430. exit (1);
  431. }
  432. if (optind < argc) {
  433. driver_nargs = 1 + argc - optind;
  434. } else {
  435. driver_nargs = 1;
  436. }
  437. if (driver_nargs == 0) {
  438. fprintf (stderr, "No driver specified ... hmm. JACK won't do"
  439. " anything when run like this.\n");
  440. return -1;
  441. }
  442. driver_args = (char **) malloc (sizeof (char *) * driver_nargs);
  443. driver_args[0] = driver_name;
  444. for (i = 1; i < driver_nargs; i++) {
  445. driver_args[i] = argv[optind++];
  446. }
  447. i = jack_parse_driver_params (desc, driver_nargs, driver_args, &driver_params);
  448. if (i)
  449. exit (0);
  450. copyright (stdout);
  451. jack_cleanup_shm ();
  452. jack_cleanup_files ();
  453. jack_main (desc, driver_params);
  454. jack_cleanup_shm ();
  455. jack_cleanup_files ();
  456. exit (0);
  457. }