+ inotify_rm_watch(fd, inot_wd);
+ close(fd);
+
+ /* Get the PID of the browserd from the lockfile */
+ if ((browserd_pid = get_browserd_pid(microb_lockfile)) <= 0) {
+ if (browserd_pid == 0)
+ log_msg("Profile lockfile link lacks PID\n");
+ else
+ log_perror(-browserd_pid,
+ "readlink() on lockfile failed");
+ exit(1);
+ }
+ free(microb_lockfile);
+
+ /* Wait for the browserd to close */
+ log_msg("Waiting for MicroB (browserd pid %d) to finish\n",
+ browserd_pid);
+ /* Clear any existing SIGCHLD handler to prevent interference
+ with our wait() */
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigemptyset(&(act.sa_mask));
+ if (sigaction(SIGCHLD, &act, &oldact) == -1) {
+ log_perror(errno, "clearing SIGCHLD handler failed");
+ exit(1);
+ }
+
+ /* Trace the browserd to get a close notification */
+ ignore_sigstop = 1;
+ if (ptrace(PTRACE_ATTACH, browserd_pid, NULL, NULL) == -1) {
+ log_perror(errno, "PTRACE_ATTACH");
+ exit(1);
+ }
+ ptrace(PTRACE_CONT, browserd_pid, NULL, NULL);
+ while ((waited_pid = wait(&status)) > 0) {
+ if (waited_pid != browserd_pid)
+ /* Not interested in other processes */
+ continue;
+ if (WIFEXITED(status) || WIFSIGNALED(status))
+ /* browserd exited */
+ break;
+ else if (WIFSTOPPED(status)) {
+ /* browserd was sent a signal
+ We're responsible for making sure this signal gets
+ delivered */
+ if (ignore_sigstop && WSTOPSIG(status) == SIGSTOP) {
+ /* Ignore the first SIGSTOP received
+ This is raised for some reason immediately
+ after we start tracing the process, and
+ won't be followed by a SIGCONT at any point
+ */
+ log_msg("Ignoring first SIGSTOP\n");
+ ptrace(PTRACE_CONT, browserd_pid, NULL, NULL);
+ ignore_sigstop = 0;
+ continue;
+ }
+ log_msg("Forwarding signal %d to browserd\n",
+ WSTOPSIG(status));
+ ptrace(PTRACE_CONT, browserd_pid, NULL,
+ WSTOPSIG(status));
+ }
+ }
+
+ /* Kill off browser UI
+ XXX: There is a race here with the restarting of the closed
+ browserd; if that happens before we kill the browser UI, the newly
+ started browserd may not close with the UI
+ XXX: Hope we don't cause data loss here! */
+ log_msg("Killing MicroB\n");
+ kill(pid, SIGTERM);
+ waitpid(pid, &status, 0);
+
+ /* Restore old SIGCHLD handler */
+ if (sigaction(SIGCHLD, &oldact, NULL) == -1) {
+ log_perror(errno, "restoring old SIGCHLD handler failed");
+ exit(1);
+ }
+}
+#endif /* FREMANTLE */
+
+void launch_microb(struct swb_context *ctx, char *uri) {
+ int kill_browserd = 0;
+ int status;
+#ifndef FREMANTLE
+ pid_t pid;
+#endif
+
+ if (!uri)
+ uri = "new_window";
+
+ log_msg("launch_microb with uri '%s'\n", uri);
+
+ /* Launch browserd if it's not running */
+ status = system("pidof browserd > /dev/null");
+ if (WIFEXITED(status) && WEXITSTATUS(status)) {
+ kill_browserd = 1;
+#ifdef FREMANTLE
+ system("/usr/sbin/browserd -d -b > /dev/null 2>&1");
+#else
+ system("/usr/sbin/browserd -d > /dev/null 2>&1");
+#endif
+ }
+
+ /* Release the osso_browser D-Bus name so that MicroB can take it */
+ dbus_release_osso_browser_name(ctx);
+
+#ifdef FREMANTLE
+ /* Do the insanity to launch Fremantle MicroB */
+ launch_microb_fremantle_with_kill(ctx, uri);