ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/prefs_editor_gtk.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/prefs_editor_gtk.cpp (file contents):
Revision 1.35 by gbeauche, 2006-04-17T21:22:01Z vs.
Revision 1.36 by gbeauche, 2006-04-18T21:29:01Z

# Line 1628 | Line 1628 | void WarningAlert(const char *text)
1628   *  RPC handlers
1629   */
1630  
1631 + static GMainLoop *g_gui_loop;
1632 +
1633   static int handle_ErrorAlert(rpc_connection_t *connection)
1634   {
1635          D(bug("handle_ErrorAlert\n"));
# Line 1660 | Line 1662 | static int handle_Exit(rpc_connection_t
1662   {
1663          D(bug("handle_Exit\n"));
1664  
1665 +        g_main_quit(g_gui_loop);
1666          return RPC_ERROR_NO_ERROR;
1667   }
1668  
1669  
1670   /*
1671 + *  SIGCHLD handler
1672 + */
1673 +
1674 + static char g_app_path[PATH_MAX];
1675 + static rpc_connection_t *g_gui_connection = NULL;
1676 +
1677 + static void sigchld_handler(int sig, siginfo_t *sip, void *)
1678 + {
1679 +        D(bug("Child %d exitted with status = %x\n", sip->si_pid, sip->si_status));
1680 +
1681 +        int status = sip->si_status;
1682 +        if (status & 0x80)
1683 +                status |= -1 ^0xff;
1684 +
1685 +        if (status < 0) {       // negative -> execlp/-errno
1686 +                char str[256];
1687 +                sprintf(str, GetString(STR_NO_B2_EXE_FOUND), g_app_path, strerror(-status));
1688 +                ErrorAlert(str);
1689 +                status = 1;
1690 +        }
1691 +
1692 +        if (status != 0) {
1693 +                if (g_gui_connection)
1694 +                        rpc_exit(g_gui_connection);
1695 +                exit(status);
1696 +        }
1697 + }
1698 +
1699 +
1700 + /*
1701   *  Start standalone GUI
1702   */
1703  
# Line 1695 | Line 1728 | int main(int argc, char *argv[])
1728                  char gui_connection_path[64];
1729                  sprintf(gui_connection_path, "/org/BasiliskII/GUI/%d", getpid());
1730  
1731 +                // Catch exits from the child process
1732 +                struct sigaction sigchld_sa, old_sigchld_sa;
1733 +                sigemptyset(&sigchld_sa.sa_mask);
1734 +                sigchld_sa.sa_sigaction = sigchld_handler;
1735 +                sigchld_sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
1736 +                if (sigaction(SIGCHLD, &sigchld_sa, &old_sigchld_sa) < 0) {
1737 +                        char str[256];
1738 +                        sprintf(str, GetString(STR_SIG_INSTALL_ERR), SIGCHLD, strerror(errno));
1739 +                        ErrorAlert(str);
1740 +                        return 1;
1741 +                }
1742 +
1743                  // Search and run the BasiliskII executable
1744                  // XXX it can be in a bundle on MacOS X
1745 <                char b2_path[PATH_MAX];
1746 <                strcpy(b2_path, argv[0]);
1747 <                char *p = strrchr(b2_path, '/');
1703 <                p = p ? p + 1 : b2_path;
1745 >                strcpy(g_app_path, argv[0]);
1746 >                char *p = strrchr(g_app_path, '/');
1747 >                p = p ? p + 1 : g_app_path;
1748                  *p = '\0';
1749 <                strcat(b2_path, "BasiliskII");
1749 >                strcat(g_app_path, "BasiliskII");
1750  
1751                  int pid = fork();
1752                  if (pid == 0) {
1753 <                        execl(b2_path, b2_path, "--gui-connection", gui_connection_path, (char *)NULL);
1754 <                        return -errno;
1753 >                        execlp(g_app_path, g_app_path, "--gui-connection", gui_connection_path, (char *)NULL);
1754 > #ifdef _POSIX_PRIORITY_SCHEDULING
1755 >                        // XXX get a chance to run the parent process so that to not confuse/upset GTK...
1756 >                        sched_yield();
1757 > #endif
1758 >                        _exit(-errno);
1759                  }
1760  
1761                  // Establish a connection to Basilisk II
1762 <                rpc_connection_t *connection;
1715 <                if ((connection = rpc_init_server(gui_connection_path)) == NULL) {
1762 >                if ((g_gui_connection = rpc_init_server(gui_connection_path)) == NULL) {
1763                          printf("ERROR: failed to initialize GUI-side RPC server connection\n");
1764                          return 1;
1765                  }
# Line 1721 | Line 1768 | int main(int argc, char *argv[])
1768                          { RPC_METHOD_WARNING_ALERT,                     handle_WarningAlert },
1769                          { RPC_METHOD_EXIT,                                      handle_Exit }
1770                  };
1771 <                if (rpc_method_add_callbacks(connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) {
1771 >                if (rpc_method_add_callbacks(g_gui_connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) {
1772                          printf("ERROR: failed to setup GUI method callbacks\n");
1773                          return 1;
1774                  }
1775                  int socket;
1776 <                if ((socket = rpc_listen_socket(connection)) < 0) {
1776 >                if ((socket = rpc_listen_socket(g_gui_connection)) < 0) {
1777                          printf("ERROR: failed to initialize RPC server thread\n");
1778                          return 1;
1779                  }
1780  
1781 <                int child_status = 1;
1782 <                GMainLoop *loop = g_main_new(TRUE);
1736 <                while (g_main_is_running(loop)) {
1781 >                g_gui_loop = g_main_new(TRUE);
1782 >                while (g_main_is_running(g_gui_loop)) {
1783  
1784                          // Process a few events pending
1785                          const int N_EVENTS_DISPATCH = 10;
# Line 1742 | Line 1788 | int main(int argc, char *argv[])
1788                                          break;
1789                          }
1790  
1791 <                        // Check if the child has terminated
1792 <                        int status = 1;
1747 <                        int ret = waitpid(pid, &status, WNOHANG);
1748 <                        if (ret == pid || (ret < 0 && errno == ECHILD)) {
1749 <                                if (WIFEXITED(status)) {
1750 <                                        child_status = WEXITSTATUS(status);
1751 <                                        if (child_status & 0x80)
1752 <                                                child_status |= -1 ^0xff;
1753 <                                }
1754 <                                break;
1755 <                        }
1756 <
1757 <                        // Check for RPC events
1758 <                        // XXX implement an rpc_try_dispatch(connection, timeout)
1759 <                        fd_set rfds;
1760 <                        FD_ZERO(&rfds);
1761 <                        FD_SET(socket, &rfds);
1762 <                        struct timeval tv;
1763 <                        tv.tv_sec = 1;
1764 <                        tv.tv_usec = 0;
1765 <                        ret = select(socket + 1, &rfds, NULL, NULL, &tv);
1766 <                        if (ret < 0)
1767 <                                break;
1791 >                        // Check for RPC events (100 ms timeout)
1792 >                        int ret = rpc_wait_dispatch(g_gui_connection, 100000);
1793                          if (ret == 0)
1794                                  continue;
1795 <                        rpc_dispatch(connection);
1796 <                }
1797 <
1773 <                rpc_exit(connection);
1774 <
1775 <                // Report failure to execute the BasiliskII binary
1776 <                if (child_status < 0) {
1777 <                        char str[256];
1778 <                        sprintf(str, GetString(STR_NO_B2_EXE_FOUND), b2_path, strerror(-child_status));
1779 <                        ErrorAlert(str);
1780 <                        return 1;
1795 >                        if (ret < 0)
1796 >                                break;
1797 >                        rpc_dispatch(g_gui_connection);
1798                  }
1799  
1800 <                return child_status;
1800 >                rpc_exit(g_gui_connection);
1801 >                return 0;
1802          }
1803  
1804          return 0;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines