From fff618aeb4142773ff388ac9b52d127a510c6690 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 6 Oct 1998 12:23:37 +0000 Subject: added a wrapper for fork() in a fork we have to close all server connections otherwise we can end up with two processes writing to the same socket. (This used to be commit b7ecbca3aff34ff06a445e5ee39efba48261b7e8) --- source3/configure | 2 +- source3/configure.in | 2 +- source3/include/config.h.in | 6 ++++ source3/smbwrapper/realcalls.h | 8 +++++ source3/smbwrapper/smbw.c | 69 ++++++++++++++++++++++++++++++++++++++++++ source3/smbwrapper/smbw_dir.c | 1 + source3/smbwrapper/wrapped.c | 5 +++ 7 files changed, 91 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/configure b/source3/configure index a807413bb6..938d6c55c7 100755 --- a/source3/configure +++ b/source3/configure @@ -4401,7 +4401,7 @@ else fi done -for ac_func in _write __write +for ac_func in _write __write _fork __fork do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:4408: checking for $ac_func" >&5 diff --git a/source3/configure.in b/source3/configure.in index c9f3ff6150..0815343ecd 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -189,7 +189,7 @@ AC_CHECK_FUNCS(_stat _lstat _fstat __stat __lstat __fstat) AC_CHECK_FUNCS(_acl __acl _facl __facl _open __open _chdir __chdir) AC_CHECK_FUNCS(_close __close _fchdir __fchdir _fcntl __fcntl) AC_CHECK_FUNCS(_getdents __getdents _lseek __lseek _read __read) -AC_CHECK_FUNCS(_write __write) +AC_CHECK_FUNCS(_write __write _fork __fork) AC_CHECK_FUNCS(_stat64 __stat64 _fstat64 __fstat64 _lstat64 __lstat64) AC_CHECK_FUNCS(llseek _llseek __llseek readdir64 _readdir64 __readdir64) AC_CHECK_FUNCS(pread _pread __pread pread64 _pread64 __pread64) diff --git a/source3/include/config.h.in b/source3/include/config.h.in index 930832a8bd..92056f075a 100644 --- a/source3/include/config.h.in +++ b/source3/include/config.h.in @@ -165,6 +165,9 @@ /* Define if you have the __fcntl function. */ #undef HAVE___FCNTL +/* Define if you have the __fork function. */ +#undef HAVE___FORK + /* Define if you have the __fstat function. */ #undef HAVE___FSTAT @@ -270,6 +273,9 @@ /* Define if you have the _fcntl function. */ #undef HAVE__FCNTL +/* Define if you have the _fork function. */ +#undef HAVE__FORK + /* Define if you have the _fstat function. */ #undef HAVE__FSTAT diff --git a/source3/smbwrapper/realcalls.h b/source3/smbwrapper/realcalls.h index 338e195087..65431bf53f 100644 --- a/source3/smbwrapper/realcalls.h +++ b/source3/smbwrapper/realcalls.h @@ -51,6 +51,14 @@ #define NO_OPEN64_ALIAS #endif +#ifdef HAVE__FORK +#define real_fork() (_fork()) +#elif HAVE___FORK +#define real_fork() (__fork()) +#elif SYS_fork +#define real_fork() (syscall(SYS_fork,())) +#endif + #ifdef HAVE__OPENDIR #define real_opendir(fn) ((DIR *)_opendir(fn)) #elif SYS_opendir diff --git a/source3/smbwrapper/smbw.c b/source3/smbwrapper/smbw.c index e5359360c3..6096f096a3 100644 --- a/source3/smbwrapper/smbw.c +++ b/source3/smbwrapper/smbw.c @@ -1229,3 +1229,72 @@ int smbw_dup2(int fd, int fd2) return -1; } + +/***************************************************** +close a connection to a server +*******************************************************/ +static void smbw_srv_close(struct smbw_server *srv) +{ + smbw_busy++; + + cli_shutdown(&srv->cli); + + free(srv->server_name); + free(srv->share_name); + + DLIST_REMOVE(smbw_srvs, srv); + + ZERO_STRUCTP(srv); + + free(srv); + + smbw_busy--; +} + +/***************************************************** +when we fork we have to close all connections and files +in the child +*******************************************************/ +int smbw_fork(void) +{ + pid_t child; + int p[2]; + char c=0; + + struct smbw_file *file, *next_file; + struct smbw_server *srv, *next_srv; + + if (pipe(p)) return real_fork(); + + child = real_fork(); + + if (child) { + /* block the parent for a moment until the sockets are + closed */ + close(p[1]); + read(p[0], &c, 1); + close(p[0]); + return child; + } + + close(p[0]); + + /* close all files */ + for (file=smbw_files;file;file=next_file) { + next_file = file->next; + close(file->fd); + } + + /* close all server connections */ + for (srv=smbw_srvs;srv;srv=next_srv) { + next_srv = srv->next; + smbw_srv_close(srv); + } + + /* unblock the parent */ + write(p[1], &c, 1); + close(p[1]); + + /* and continue in the child */ + return 0; +} diff --git a/source3/smbwrapper/smbw_dir.c b/source3/smbwrapper/smbw_dir.c index a932c102dc..2c1b7ef9ec 100644 --- a/source3/smbwrapper/smbw_dir.c +++ b/source3/smbwrapper/smbw_dir.c @@ -664,3 +664,4 @@ off_t smbw_telldir(DIR *dirp) struct smbw_dir *d = (struct smbw_dir *)dirp; return smbw_dir_lseek(d->fd,0,SEEK_CUR); } + diff --git a/source3/smbwrapper/wrapped.c b/source3/smbwrapper/wrapped.c index bda0ed1abe..10b22b35dd 100644 --- a/source3/smbwrapper/wrapped.c +++ b/source3/smbwrapper/wrapped.c @@ -908,3 +908,8 @@ static void dirent64_convert(struct dirent *d, struct dirent64 *d64) return real_readdir64(dir); } #endif + + int fork(void) +{ + return smbw_fork(); +} -- cgit