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.

475 lines
11KB

  1. /*
  2. Copyright (C) 2001-2003 Paul Davis
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. $Id$
  15. */
  16. #include <stdio.h>
  17. #include <signal.h>
  18. #include <getopt.h>
  19. #include <sys/types.h>
  20. #include <sys/shm.h>
  21. #include <sys/wait.h>
  22. #include <string.h>
  23. #include <errno.h>
  24. #include <config.h>
  25. #include <jack/engine.h>
  26. #include <jack/internal.h>
  27. #include <jack/driver.h>
  28. #include <jack/shm.h>
  29. #ifdef USE_CAPABILITIES
  30. #include <sys/stat.h>
  31. /* capgetp and capsetp are linux only extensions, not posix */
  32. #undef _POSIX_SOURCE
  33. #include <sys/capability.h>
  34. #include <jack/start.h>
  35. static struct stat pipe_stat;
  36. #endif
  37. static sigset_t signals;
  38. static jack_engine_t *engine = 0;
  39. static int jackd_pid;
  40. static int realtime = 0;
  41. static int realtime_priority = 10;
  42. static int with_fork = 1;
  43. static int verbose = 0;
  44. static int asio_mode = 0;
  45. static int client_timeout = 500; /* msecs */
  46. typedef struct {
  47. pid_t pid;
  48. int argc;
  49. char **argv;
  50. } waiter_arg_t;
  51. static void
  52. signal_handler (int sig)
  53. {
  54. /* this is used by the parent (waiter) process */
  55. fprintf (stderr, "jackd: signal %d received\n", sig);
  56. kill (jackd_pid, SIGTERM);
  57. }
  58. static void
  59. do_nothing_handler (int sig)
  60. {
  61. /* this is used by the child (active) process, but it never
  62. gets called unless we are already shutting down after
  63. another signal.
  64. */
  65. char buf[64];
  66. snprintf (buf, sizeof(buf),
  67. "received signal %d during shutdown (ignored)\n", sig);
  68. write (1, buf, strlen (buf));
  69. }
  70. static void *
  71. jack_engine_waiter_thread (void *arg)
  72. {
  73. waiter_arg_t *warg = (waiter_arg_t *) arg;
  74. pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  75. if ((engine = jack_engine_new (realtime, realtime_priority,
  76. verbose, client_timeout)) == 0) {
  77. fprintf (stderr, "cannot create engine\n");
  78. kill (warg->pid, SIGTERM);
  79. return 0;
  80. }
  81. if (warg->argc) {
  82. fprintf (stderr, "loading driver ..\n");
  83. if (jack_engine_load_driver (engine, warg->argc, warg->argv)) {
  84. fprintf (stderr, "cannot load driver module %s\n",
  85. warg->argv[0]);
  86. kill (warg->pid, SIGTERM);
  87. return 0;
  88. }
  89. } else {
  90. fprintf (stderr, "No driver specified ... hmm. JACK won't do"
  91. " anything when run like this.\n");
  92. }
  93. if (asio_mode) {
  94. jack_set_asio_mode (engine, TRUE);
  95. }
  96. fprintf (stderr, "starting engine\n");
  97. if (jack_run (engine)) {
  98. fprintf (stderr, "cannot start main JACK thread\n");
  99. kill (warg->pid, SIGTERM);
  100. return 0;
  101. }
  102. jack_wait (engine);
  103. fprintf (stderr, "telling signal thread that the engine is done\n");
  104. kill (warg->pid, SIGHUP);
  105. return 0; /* nobody cares what this returns */
  106. }
  107. static void
  108. jack_main (int argc, char **argv)
  109. {
  110. int sig;
  111. int i;
  112. pthread_t waiter_thread;
  113. waiter_arg_t warg;
  114. sigset_t allsignals;
  115. struct sigaction action;
  116. /* remove any existing files from a previous instance */
  117. jack_cleanup_files ();
  118. pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  119. /* what's this for?
  120. POSIX says that signals are delivered like this:
  121. * if a thread has blocked that signal, it is not
  122. a candidate to receive the signal.
  123. * of all threads not blocking the signal, pick
  124. one at random, and deliver the signal.
  125. this means that a simple-minded multi-threaded program can
  126. expect to get POSIX signals delivered randomly to any one
  127. of its threads,
  128. here, we block all signals that we think we might receive
  129. and want to catch. all "child" threads will inherit this
  130. setting. if we create a thread that calls sigwait() on the
  131. same set of signals, implicitly unblocking all those
  132. signals. any of those signals that are delivered to the
  133. process will be delivered to that thread, and that thread
  134. alone. this makes cleanup for a signal-driven exit much
  135. easier, since we know which thread is doing it and more
  136. importantly, we are free to call async-unsafe functions,
  137. because the code is executing in normal thread context
  138. after a return from sigwait().
  139. */
  140. sigemptyset (&signals);
  141. sigaddset(&signals, SIGHUP);
  142. sigaddset(&signals, SIGINT);
  143. sigaddset(&signals, SIGQUIT);
  144. sigaddset(&signals, SIGILL);
  145. sigaddset(&signals, SIGTRAP);
  146. sigaddset(&signals, SIGABRT);
  147. sigaddset(&signals, SIGIOT);
  148. sigaddset(&signals, SIGFPE);
  149. sigaddset(&signals, SIGPIPE);
  150. sigaddset(&signals, SIGTERM);
  151. sigaddset(&signals, SIGUSR1);
  152. sigaddset(&signals, SIGSEGV);
  153. /* all child threads will inherit this mask unless they
  154. * explicitly reset it */
  155. pthread_sigmask (SIG_BLOCK, &signals, 0);
  156. /* what we'd really like to do here is to be able to wait for
  157. either the engine to stop or a POSIX signal, whichever
  158. arrives sooner. but there is no mechanism to do that, so
  159. instead we create a thread to wait for the engine to
  160. finish, and here we stop and wait for any (reasonably
  161. likely) POSIX signal.
  162. if the engine finishes first, the waiter thread will tell
  163. us about it via a signal.
  164. if a signal arrives, we'll stop the engine and then exit.
  165. in normal operation, our parent process will be waiting for
  166. us and will cleanup.
  167. */
  168. warg.pid = getpid();
  169. warg.argc = argc;
  170. warg.argv = argv;
  171. if (pthread_create (&waiter_thread, 0, jack_engine_waiter_thread,
  172. &warg)) {
  173. fprintf (stderr,
  174. "jackd: cannot create engine waiting thread\n");
  175. return;
  176. }
  177. /* install a do-nothing handler because otherwise pthreads
  178. behaviour is undefined when we enter sigwait.
  179. */
  180. sigfillset (&allsignals);
  181. action.sa_handler = do_nothing_handler;
  182. action.sa_mask = allsignals;
  183. action.sa_flags = SA_RESTART|SA_RESETHAND;
  184. for (i = 1; i < NSIG; i++) {
  185. if (sigismember (&signals, i)) {
  186. sigaction (i, &action, 0);
  187. }
  188. }
  189. if (verbose) {
  190. fprintf (stderr, "%d waiting for signals\n", getpid());
  191. }
  192. while(1) {
  193. sigwait (&signals, &sig);
  194. fprintf (stderr, "jack main caught signal %d\n", sig);
  195. if (sig == SIGUSR1) {
  196. jack_dump_configuration(engine, 1);
  197. } else {
  198. /* continue to kill engine */
  199. break;
  200. }
  201. }
  202. if (sig != SIGSEGV) {
  203. /* unblock signals so we can see them during shutdown.
  204. this will help prod developers not to lose sight of
  205. bugs that cause segfaults etc. during shutdown.
  206. */
  207. sigprocmask (SIG_UNBLOCK, &signals, 0);
  208. }
  209. pthread_cancel (waiter_thread);
  210. jack_engine_delete (engine);
  211. return;
  212. }
  213. static void copyright (FILE* file)
  214. {
  215. fprintf (file, "jackd " VERSION "\n"
  216. "Copyright 2001-2003 Paul Davis and others.\n"
  217. "jackd comes with ABSOLUTELY NO WARRANTY\n"
  218. "This is free software, and you are welcome to redistribute it\n"
  219. "under certain conditions; see the file COPYING for details\n\n");
  220. }
  221. static void usage (FILE *file)
  222. {
  223. copyright (file);
  224. fprintf (file, "\n"
  225. "usage: jackd [ --asio OR -a ]\n"
  226. " [ --realtime OR -R [ --realtime-priority OR -P priority ] ]\n"
  227. " [ --timeout OR -t client-timeout-in-msecs ]\n"
  228. " [ --verbose OR -v ]\n"
  229. " [ --tmpdir OR -D directory-for-temporary-files ]\n"
  230. " [ --version OR -V ]\n"
  231. " -d driver [ ... driver args ... ]\n");
  232. }
  233. int
  234. main (int argc, char *argv[])
  235. {
  236. const char *options = "-ad:D:P:vhVRFl:t:";
  237. struct option long_options[] =
  238. {
  239. { "asio", 0, 0, 'a' },
  240. { "driver", 1, 0, 'd' },
  241. { "tmpdir", 1, 0, 'D' },
  242. { "verbose", 0, 0, 'v' },
  243. { "help", 0, 0, 'h' },
  244. { "realtime", 0, 0, 'R' },
  245. { "realtime-priority", 1, 0, 'P' },
  246. { "timeout", 1, 0, 't' },
  247. { "spoon", 0, 0, 'F' },
  248. { "version", 0, 0, 'V' },
  249. { 0, 0, 0, 0 }
  250. };
  251. int option_index;
  252. int opt;
  253. int seen_driver = 0;
  254. char *driver_name = 0;
  255. char **driver_args = 0;
  256. int driver_nargs = 1;
  257. int show_version = 0;
  258. int i;
  259. #ifdef USE_CAPABILITIES
  260. int status;
  261. #endif
  262. #ifdef USE_CAPABILITIES
  263. /* check to see if there is a pipe in the right descriptor */
  264. if ((status = fstat (PIPE_WRITE_FD, &pipe_stat)) == 0 &&
  265. S_ISFIFO(pipe_stat.st_mode)) {
  266. /* tell jackstart we are up and running */
  267. char c = 1;
  268. if (write (PIPE_WRITE_FD, &c, 1) != 1) {
  269. fprintf (stderr, "cannot write to jackstart sync "
  270. "pipe %d (%s)\n", PIPE_WRITE_FD,
  271. strerror (errno));
  272. }
  273. if (close(PIPE_WRITE_FD) != 0) {
  274. fprintf(stderr,
  275. "jackd: error on startup pipe close: %s\n",
  276. strerror (errno));
  277. } else {
  278. /* wait for jackstart process to set our capabilities */
  279. if (wait (&status) == -1) {
  280. fprintf (stderr, "jackd: wait for startup "
  281. "process exit failed\n");
  282. }
  283. if (!WIFEXITED (status) || WEXITSTATUS (status)) {
  284. fprintf(stderr, "jackd: jackstart did not "
  285. "exit cleanly\n");
  286. exit (1);
  287. }
  288. }
  289. }
  290. #endif
  291. opterr = 0;
  292. while (!seen_driver && (opt = getopt_long (argc, argv, options,
  293. long_options,
  294. &option_index)) != EOF) {
  295. switch (opt) {
  296. case 'a':
  297. asio_mode = TRUE;
  298. break;
  299. case 'D':
  300. jack_set_server_dir (optarg);
  301. break;
  302. case 'd':
  303. seen_driver = 1;
  304. driver_name = optarg;
  305. break;
  306. case 'v':
  307. verbose = 1;
  308. break;
  309. case 'F':
  310. with_fork = 0;
  311. break;
  312. case 'P':
  313. realtime_priority = atoi (optarg);
  314. break;
  315. case 'R':
  316. realtime = 1;
  317. break;
  318. case 't':
  319. client_timeout = atoi (optarg);
  320. break;
  321. case 'V':
  322. show_version = 1;
  323. break;
  324. default:
  325. fprintf (stderr, "unknown option character %c\n",
  326. optopt);
  327. /*fallthru*/
  328. case 'h':
  329. usage (stdout);
  330. return -1;
  331. }
  332. }
  333. if (show_version) {
  334. printf ( "jackd version " VERSION "\n");
  335. #ifdef DEFAULT_TMP_DIR
  336. printf ( "default tmp directory: " DEFAULT_TMP_DIR "\n");
  337. #else
  338. printf ( "default tmp directory: /tmp\n");
  339. #endif
  340. return -1;
  341. }
  342. if (!seen_driver) {
  343. usage (stderr);
  344. exit (1);
  345. }
  346. if (optind < argc) {
  347. driver_nargs = 1 + argc - optind;
  348. } else {
  349. driver_nargs = 1;
  350. }
  351. driver_args = (char **) malloc (sizeof (char *) * driver_nargs);
  352. driver_args[0] = driver_name;
  353. for (i = 1; i < driver_nargs; i++) {
  354. driver_args[i] = argv[optind++];
  355. }
  356. copyright (stdout);
  357. if (!with_fork) {
  358. /* This is really here so that we can run gdb easily */
  359. jack_main (driver_nargs, driver_args);
  360. } else {
  361. int pid = fork ();
  362. if (pid < 0) {
  363. fprintf (stderr, "could not fork jack server (%s)",
  364. strerror (errno));
  365. exit (1);
  366. } else if (pid == 0) {
  367. jack_main (driver_nargs, driver_args);
  368. } else {
  369. jackd_pid = pid;
  370. signal (SIGHUP, signal_handler);
  371. signal (SIGINT, signal_handler);
  372. signal (SIGQUIT, signal_handler);
  373. signal (SIGTERM, signal_handler);
  374. waitpid (pid, NULL, 0);
  375. }
  376. }
  377. jack_cleanup_shm ();
  378. jack_cleanup_files ();
  379. return 0;
  380. }