diff options
| author | Gerd Moellmann | 2000-09-30 13:51:15 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 2000-09-30 13:51:15 +0000 |
| commit | 70dbdb363e8612357facf9b05184c93098de1658 (patch) | |
| tree | 360184270117dbc98a4ea3ead093c316ab776e13 /src | |
| parent | d777bb8fc4a1a518ee410fc7e80a9f4ffcf352e0 (diff) | |
| download | emacs-70dbdb363e8612357facf9b05184c93098de1658.tar.gz emacs-70dbdb363e8612357facf9b05184c93098de1658.zip | |
(Fopen_network_stream) [HAVE_GETADDRINFO]: Use
gai_strerror. Make sure xerrno is set if connect fails. Improve
error recovery.
Diffstat (limited to 'src')
| -rw-r--r-- | src/process.c | 103 |
1 files changed, 65 insertions, 38 deletions
diff --git a/src/process.c b/src/process.c index 8ce822fdb1b..1fcbc2311a3 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -1748,18 +1748,18 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ | |||
| 1748 | Lisp_Object name, buffer, host, service; | 1748 | Lisp_Object name, buffer, host, service; |
| 1749 | { | 1749 | { |
| 1750 | Lisp_Object proc; | 1750 | Lisp_Object proc; |
| 1751 | #ifndef HAVE_GETADDRINFO | 1751 | #ifdef HAVE_GETADDRINFO |
| 1752 | struct addrinfo hints, *res, *lres; | ||
| 1753 | int ret = 0; | ||
| 1754 | int xerrno = 0; | ||
| 1755 | char *portstring, portbuf[128]; | ||
| 1756 | #else /* HAVE_GETADDRINFO */ | ||
| 1752 | struct sockaddr_in address; | 1757 | struct sockaddr_in address; |
| 1753 | struct servent *svc_info; | 1758 | struct servent *svc_info; |
| 1754 | struct hostent *host_info_ptr, host_info; | 1759 | struct hostent *host_info_ptr, host_info; |
| 1755 | char *(addr_list[2]); | 1760 | char *(addr_list[2]); |
| 1756 | IN_ADDR numeric_addr; | 1761 | IN_ADDR numeric_addr; |
| 1757 | int port; | 1762 | int port; |
| 1758 | #else /* HAVE_GETADDRINFO */ | ||
| 1759 | struct addrinfo hints, *res, *lres; | ||
| 1760 | int ret = 0; | ||
| 1761 | int xerrno = 0; | ||
| 1762 | char *portstring, portbuf[128]; | ||
| 1763 | #endif /* HAVE_GETADDRINFO */ | 1763 | #endif /* HAVE_GETADDRINFO */ |
| 1764 | int s = -1, outch, inch; | 1764 | int s = -1, outch, inch; |
| 1765 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 1765 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
| @@ -1777,13 +1777,11 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ | |||
| 1777 | CHECK_STRING (host, 0); | 1777 | CHECK_STRING (host, 0); |
| 1778 | 1778 | ||
| 1779 | #ifdef HAVE_GETADDRINFO | 1779 | #ifdef HAVE_GETADDRINFO |
| 1780 | /* | 1780 | /* SERVICE can either be a string or int. |
| 1781 | * SERVICE can either be a string or int. | 1781 | Convert to a C string for later use by getaddrinfo. */ |
| 1782 | * Convert to a C string for later use by getaddrinfo. | ||
| 1783 | */ | ||
| 1784 | if (INTEGERP (service)) | 1782 | if (INTEGERP (service)) |
| 1785 | { | 1783 | { |
| 1786 | sprintf (portbuf, "%d", XINT (service)); | 1784 | sprintf (portbuf, "%ld", (long) XINT (service)); |
| 1787 | portstring = portbuf; | 1785 | portstring = portbuf; |
| 1788 | } | 1786 | } |
| 1789 | else | 1787 | else |
| @@ -1791,7 +1789,7 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ | |||
| 1791 | CHECK_STRING (service, 0); | 1789 | CHECK_STRING (service, 0); |
| 1792 | portstring = XSTRING (service)->data; | 1790 | portstring = XSTRING (service)->data; |
| 1793 | } | 1791 | } |
| 1794 | #else /* ! HAVE_GETADDRINFO */ | 1792 | #else /* HAVE_GETADDRINFO */ |
| 1795 | if (INTEGERP (service)) | 1793 | if (INTEGERP (service)) |
| 1796 | port = htons ((unsigned short) XINT (service)); | 1794 | port = htons ((unsigned short) XINT (service)); |
| 1797 | else | 1795 | else |
| @@ -1802,7 +1800,7 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ | |||
| 1802 | error ("Unknown service \"%s\"", XSTRING (service)->data); | 1800 | error ("Unknown service \"%s\"", XSTRING (service)->data); |
| 1803 | port = svc_info->s_port; | 1801 | port = svc_info->s_port; |
| 1804 | } | 1802 | } |
| 1805 | #endif /* ! HAVE_GETADDRINFO */ | 1803 | #endif /* HAVE_GETADDRINFO */ |
| 1806 | 1804 | ||
| 1807 | 1805 | ||
| 1808 | /* Slow down polling to every ten seconds. | 1806 | /* Slow down polling to every ten seconds. |
| @@ -1815,32 +1813,30 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ | |||
| 1815 | 1813 | ||
| 1816 | #ifndef TERM | 1814 | #ifndef TERM |
| 1817 | #ifdef HAVE_GETADDRINFO | 1815 | #ifdef HAVE_GETADDRINFO |
| 1818 | { | 1816 | immediate_quit = 1; |
| 1819 | immediate_quit = 1; | 1817 | QUIT; |
| 1820 | QUIT; | 1818 | memset (&hints, 0, sizeof (hints)); |
| 1821 | memset (&hints, 0, sizeof (hints)); | 1819 | hints.ai_flags = 0; |
| 1822 | hints.ai_flags = 0; | 1820 | hints.ai_family = AF_UNSPEC; |
| 1823 | hints.ai_family = AF_UNSPEC; | 1821 | hints.ai_socktype = SOCK_STREAM; |
| 1824 | hints.ai_socktype = SOCK_STREAM; | 1822 | hints.ai_protocol = 0; |
| 1825 | hints.ai_protocol = 0; | 1823 | ret = getaddrinfo (XSTRING (host)->data, portstring, &hints, &res); |
| 1826 | ret = getaddrinfo (XSTRING (host)->data, portstring, &hints, &res); | 1824 | if (ret) |
| 1827 | if (ret) | 1825 | error ("%s/%s %s", XSTRING (host)->data, portstring, gai_strerror(ret)); |
| 1828 | { | 1826 | immediate_quit = 0; |
| 1829 | error ("%s/%s %s", XSTRING (host)->data, portstring, | ||
| 1830 | strerror (ret)); | ||
| 1831 | } | ||
| 1832 | immediate_quit = 0; | ||
| 1833 | } | ||
| 1834 | 1827 | ||
| 1835 | s = -1; | 1828 | /* Do this in case we never enter the for-loop below. */ |
| 1836 | count1 = specpdl_ptr - specpdl; | 1829 | count1 = specpdl_ptr - specpdl; |
| 1837 | record_unwind_protect (close_file_unwind, make_number (s)); | 1830 | s = -1; |
| 1838 | 1831 | ||
| 1839 | for (lres = res; lres; lres = lres->ai_next) | 1832 | for (lres = res; lres; lres = lres->ai_next) |
| 1840 | { | 1833 | { |
| 1841 | s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol); | 1834 | s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol); |
| 1842 | if (s < 0) | 1835 | if (s < 0) |
| 1843 | continue; | 1836 | { |
| 1837 | xerrno = errno; | ||
| 1838 | continue; | ||
| 1839 | } | ||
| 1844 | 1840 | ||
| 1845 | /* Kernel bugs (on Ultrix at least) cause lossage (not just EINTR) | 1841 | /* Kernel bugs (on Ultrix at least) cause lossage (not just EINTR) |
| 1846 | when connect is interrupted. So let's not let it get interrupted. | 1842 | when connect is interrupted. So let's not let it get interrupted. |
| @@ -1851,6 +1847,12 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ | |||
| 1851 | if (interrupt_input) | 1847 | if (interrupt_input) |
| 1852 | unrequest_sigio (); | 1848 | unrequest_sigio (); |
| 1853 | 1849 | ||
| 1850 | /* Make us close S if quit. */ | ||
| 1851 | count1 = specpdl_ptr - specpdl; | ||
| 1852 | record_unwind_protect (close_file_unwind, make_number (s)); | ||
| 1853 | |||
| 1854 | loop: | ||
| 1855 | |||
| 1854 | immediate_quit = 1; | 1856 | immediate_quit = 1; |
| 1855 | QUIT; | 1857 | QUIT; |
| 1856 | 1858 | ||
| @@ -1863,11 +1865,33 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ | |||
| 1863 | though. Would non-blocking connect calls be portable? */ | 1865 | though. Would non-blocking connect calls be portable? */ |
| 1864 | turn_on_atimers (0); | 1866 | turn_on_atimers (0); |
| 1865 | ret = connect (s, lres->ai_addr, lres->ai_addrlen); | 1867 | ret = connect (s, lres->ai_addr, lres->ai_addrlen); |
| 1868 | xerrno = errno; | ||
| 1866 | turn_on_atimers (1); | 1869 | turn_on_atimers (1); |
| 1867 | if (ret == 0) | 1870 | |
| 1871 | if (ret == 0 || xerrno == EISCONN) | ||
| 1872 | /* The unwind-protect will be discarded afterwards. | ||
| 1873 | Likewise for immediate_quit. */ | ||
| 1868 | break; | 1874 | break; |
| 1875 | |||
| 1876 | immediate_quit = 0; | ||
| 1877 | |||
| 1878 | if (xerrno == EINTR) | ||
| 1879 | goto loop; | ||
| 1880 | if (xerrno == EADDRINUSE && retry < 20) | ||
| 1881 | { | ||
| 1882 | /* A delay here is needed on some FreeBSD systems, | ||
| 1883 | and it is harmless, since this retrying takes time anyway | ||
| 1884 | and should be infrequent. */ | ||
| 1885 | Fsleep_for (make_number (1), Qnil); | ||
| 1886 | retry++; | ||
| 1887 | goto loop; | ||
| 1888 | } | ||
| 1889 | |||
| 1890 | /* Discard the unwind protect closing S. */ | ||
| 1891 | specpdl_ptr = specpdl + count1; | ||
| 1892 | count1 = specpdl_ptr - specpdl; | ||
| 1893 | |||
| 1869 | emacs_close (s); | 1894 | emacs_close (s); |
| 1870 | s = -1; | ||
| 1871 | } | 1895 | } |
| 1872 | 1896 | ||
| 1873 | freeaddrinfo (res); | 1897 | freeaddrinfo (res); |
| @@ -1880,7 +1904,8 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ | |||
| 1880 | report_file_error ("connection failed", | 1904 | report_file_error ("connection failed", |
| 1881 | Fcons (host, Fcons (name, Qnil))); | 1905 | Fcons (host, Fcons (name, Qnil))); |
| 1882 | } | 1906 | } |
| 1883 | #else /* ! HAVE_GETADDRINFO */ | 1907 | |
| 1908 | #else /* not HAVE_GETADDRINFO */ | ||
| 1884 | 1909 | ||
| 1885 | while (1) | 1910 | while (1) |
| 1886 | { | 1911 | { |
| @@ -1901,6 +1926,7 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ | |||
| 1901 | break; | 1926 | break; |
| 1902 | Fsleep_for (make_number (1), Qnil); | 1927 | Fsleep_for (make_number (1), Qnil); |
| 1903 | } | 1928 | } |
| 1929 | |||
| 1904 | if (host_info_ptr == 0) | 1930 | if (host_info_ptr == 0) |
| 1905 | /* Attempt to interpret host as numeric inet address */ | 1931 | /* Attempt to interpret host as numeric inet address */ |
| 1906 | { | 1932 | { |
| @@ -1982,11 +2008,12 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ | |||
| 1982 | report_file_error ("connection failed", | 2008 | report_file_error ("connection failed", |
| 1983 | Fcons (host, Fcons (name, Qnil))); | 2009 | Fcons (host, Fcons (name, Qnil))); |
| 1984 | } | 2010 | } |
| 1985 | #endif /* ! HAVE_GETADDRINFO */ | 2011 | |
| 2012 | #endif /* not HAVE_GETADDRINFO */ | ||
| 1986 | 2013 | ||
| 1987 | immediate_quit = 0; | 2014 | immediate_quit = 0; |
| 1988 | 2015 | ||
| 1989 | /* Discard the unwind protect. */ | 2016 | /* Discard the unwind protect, if any. */ |
| 1990 | specpdl_ptr = specpdl + count1; | 2017 | specpdl_ptr = specpdl + count1; |
| 1991 | 2018 | ||
| 1992 | #ifdef POLL_FOR_INPUT | 2019 | #ifdef POLL_FOR_INPUT |