--Boundary-00=_QOpBA623HMowced Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Hello whoever, I send you a patch to avoid that Konqueror hangs and Syslogd quickly fills= =20 your harddisk with error messages. The problem occurs with mmap() and files= =20 that are accessed via smb (or nfs) and are not accessible due to ownership= =20 and protection on the server side. See the remark concerning nfs in 'man 2= =20 access'. Typically the problem shows up with konqueror and the .directory=20 file. Lots of lines containing just the work "SIGBUS" are written to stderr= =20 and konqueror hangs. About the current implementation in kconfigbackend.cpp: mmap() is used alwa= ys =20 to read conf files. Interrestingly the author was aware of a SIGBUS problem= =20 and tried to recover from the SIGBUS. BUT THIS DOES NOT WORK. Maybe it neve= r=20 worked? Or maybe it's a compiler optimization problem. About the patch: as mmap() may return unaccessible memory, the use of mmap = is=20 restricted now to large files. In any case a classical read() syscall is us= ed=20 either to read an entiere small conf file, or to probe if the (large) file = is=20 readable. If the read succeeds for a large file, mmap is used as before. mm= ap=20 is not trivial for the kernel, maybe this patch also gives a little speed=20 improvement. The patch is against today's HEAD (3.1.94 plus updates). I also attach a little test program that can be used to play with access() = and=20 mmap() if you don't trust me. My kernel is a 2.4.21 from Mantel/SuSE. I am= =20 using a P4 and the problem occurred also in older Versions of KDE. Yours J=FCrgen --Boundary-00=_QOpBA623HMowced Content-Type: text/x-diff; charset="us-ascii"; name="jpf.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="jpf.patch" --- kconfigbackend.cpp 2004-01-15 13:16:49.000000000 +0100 +++ kconfigbackend.cpp 2004-01-15 13:11:06.000000000 +0100 @@ -367,13 +367,14 @@ #ifdef HAVE_MMAP #ifdef SIGBUS -static const char **mmap_pEof; static void mmap_sigbus_handler(int) { - *mmap_pEof = 0; - write(2, "SIGBUS\n", 7); - signal(SIGBUS, mmap_sigbus_handler); + const char* pMsg = "FATAL: KConfigBackend " + "cannot recover from SIGBUS error on mmap'ed config file\n"; + write(2, pMsg, strlen(pMsg)); + // we must commit suicide, otherwise we an infinite loop + _exit(2); } #endif #endif @@ -399,33 +400,58 @@ unsigned int ll = localeString.length(); -#ifdef HAVE_MMAP - const char *map = ( const char* ) mmap(0, rFile.size(), PROT_READ, MAP_PRIVATE, - rFile.handle(), 0); + bool fileOptionImmutable = false; + bool groupOptionImmutable = false; + bool groupSkip = false; - if (map) - { - s = map; + // mmap is fast for large config files but can fail to return readable + // memory for smb or nfs mounts (see access() manpage). The fastest + // workaround is to probe files using read(). Small files are read + // directly, large files are left to mmap(). + + char sBuffer[1024]; + int iOK; + if(rFile.size() <= sizeof(sBuffer)) + { s = sBuffer; eof = s + rFile.size(); - -#ifdef SIGBUS - mmap_pEof = &eof; - old_sighandler = signal(SIGBUS, mmap_sigbus_handler); -#endif + iOK = read(rFile.handle(), sBuffer, rFile.size()); } else + { s = eof = 0; + iOK = read(rFile.handle(), sBuffer, 1); + } + if(iOK < 0) + { // kdDebug cannot be used here? + fprintf(stderr, "KConfigBackend cannot read file: %s\n", rFile.name().latin1()); + return; + } + +#ifdef HAVE_MMAP + const char *map = 0; // we need it for munmap() #endif + if(s == 0) { - rFile.at(0); - data = rFile.readAll(); - s = data.data(); - eof = s + data.size(); +#ifdef HAVE_MMAP + map = (const char*)mmap(0, rFile.size(), PROT_READ, MAP_PRIVATE, + rFile.handle(), 0); + if(map) + { s = map; + eof = s + rFile.size(); + // SIGBUS cannot be used to recover invalid memory access! +#ifdef SIGBUS + old_sighandler = signal(SIGBUS, mmap_sigbus_handler); +#endif + } + else +#endif + { // use qt if mmap is not availlable + rFile.at(0); + data = rFile.readAll(); + s = data.data(); + eof = s + data.size(); + } } - bool fileOptionImmutable = false; - bool groupOptionImmutable = false; - bool groupSkip = false; - int line = 0; for(; s < eof; s++) { @@ -447,7 +473,7 @@ if (*s == '[') //group { // In a group [[ and ]] have a special meaning - while ((s < eof) && (*s != '\n')) + while ((s < eof) && (*s != '\n')) { if (*s == ']') { --Boundary-00=_QOpBA623HMowced Content-Type: text/x-c++src; charset="us-ascii"; name="smbproblem.cpp" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="smbproblem.cpp" #include #include #include #include #include #include #include #include #include char* pX; void sighandler(int iSig) { printf("sighandler %d\n", iSig); pX = ""; } int main() { const char* pszFile = "/Filme/Server/.directory"; printf("testing: %s\n", pszFile); // access won't help ... int ia = access(pszFile, R_OK); printf("access returns %x\n", ia); // open doesn't fail ... int io = open(pszFile, O_RDONLY); printf("open returns %x\n", io); // fstat works ... struct stat st; int is = fstat(io, &st); printf("fstat() returns %x mode %x uid %d gid %d\n", is, st.st_mode, st.st_uid, st.st_gid); // read fails ... char buff[128]; int ir = read(io, buff, st.st_size); if(ir >= 0) printf("read() returns %d\n", ir); else perror("read() status"); // mmap succeeds ... void* pMap = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, io, 0); if(pMap) printf("mmap() returns %x\n", pMap); else perror("mmap() status"); // write using the mmap memory fails int iw = write(0, pMap, 1); if(iw >= 0) printf("write() returns %x\n", iw); else perror("write() status"); // THIS IS CURRENTLY IN KDE AND IS WRONG! // signal(SIGBUS, sighandler); // printf("data %x\n", pX[0]); return 0; } --Boundary-00=_QOpBA623HMowced--