Issue1102879
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2005-01-15 11:37 by irmen, last changed 2022-04-11 14:56 by admin. This issue is now closed.
Files | ||||
---|---|---|---|---|
File name | Uploaded | Description | Edit | |
patch.txt | irmen, 2005-01-15 11:37 | patch for Modules/socketmodule.c |
Messages (7) | |||
---|---|---|---|
msg47541 - (view) | Author: Irmen de Jong (irmen) | Date: 2005-01-15 11:37 | |
Please have a close look at the attached patch. Essentially, it fixes internal_select to not return zero on error condition, and also adds a test for errno at all calls to internal_select. A few remarks: 1) as indicated in the patch, I'm not sure if errno should also be tested in the internal_connect function; 2) 'timeout' is no longer a boolean indicating a timeout condition, it should probably be renamed to 'selectresult' or something similar; 3) I'm not too happy with the fact that the if(timeout==-1 && erro) test must be duplicated in a lot of functions; 4) does it do the right thing? The check for timeout==-1 MUST be there otherwise a lot of errors turn up in the regression tests. With this patch they run fine, btw |
|||
msg47542 - (view) | Author: Martin v. Löwis (loewis) * | Date: 2005-02-24 20:42 | |
Logged In: YES user_id=21627 Thanks for the patch. 1) I could not see where you dealt with internal_connect in the patch. However, as a connect can also be cancelled with Ctrl-C, I think you need to deal with it, too. 2) I agree, renaming it would be good 3) you could come up with a macro to avoid code duplication (relying on consistent naming of variables, but that might confure more than help 4) This is almost right. The critical thing is that you read errno much too late. errno is meant to be read immediately after the system call. Any later system call can modify the value - including all of the pthread calls that we do in-between. So the right solution is to copy errno right after select, into a local variable of the caller, and read *that* variable. In order to avoid modifying SetFromErrno, you can assign back to errno before calling it. |
|||
msg47543 - (view) | Author: Tony Nelson (tony_nelson) | Date: 2006-06-18 18:00 | |
Logged In: YES user_id=1356214 Martin, I'm working on an update to this patch so that it will finally get fixed. I have a question about your answer to #4. You say that errno is read "much too late", but that's the same way that errorhandler() does it, and it seems acceptable there. I don't see any calls in between that would trash errno (at least after my patch is applied :). Is there really a problem? I do have it fixed, by returning errno from internal_select(), but if it isn't needed I'd like to simplify the patch. BTW, I'm handling #1 (internal_connect()). There is still more work to do -- I think that it would be better to handle Ctl-C as the interpreter does on its periodic checks, so that it becomes KeyboardInterrupt instead of some other error with a ' (4, ' in it. Umm, I need to do more research on that. |
|||
msg47544 - (view) | Author: Martin v. Löwis (loewis) * | Date: 2006-06-18 18:23 | |
Logged In: YES user_id=21627 If I understand correctly, you have Py_END_ALLOW_THREADS between the system call and the access to errno. Py_END_ALLOW_THREADS expands to PyEval_RestoreThread, which calls PyThread_acquire_lock, which (on pthreads) calls sem_wait, which may set errno to EINTR. It may well be that the same mistake is made in other places. That the code is in Python is no proof that it is "acceptable" - only that earlier reviewers did not catch the mistake. If so, this should perhaps be discussed on python-dev: if we want an explicit guarantee that errno won't change across these macros, we should change the functions to provide that guarantee. In general, you should assume that any C library call may change errno, unless it does not document the values that errno may receive due to this system call. So for any library call between the original call and the usage of errno, you have to analyse whether it may change errno (directly or indirectly). |
|||
msg47545 - (view) | Author: Tony Nelson (tony_nelson) | Date: 2006-06-18 19:22 | |
Logged In: YES user_id=1356214 Hmm, not me, but yes, socketmodule.c wraps its system calls in Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS, and then does its error checking. Here's a small function (from trunk): static PyObject * sock_connect(PySocketSockObject *s, PyObject *addro) { struct sockaddr *addr; int addrlen; int res; int timeout; if (!getsockaddrarg(s, addro, &addr, &addrlen)) return NULL; Py_BEGIN_ALLOW_THREADS res = internal_connect(s, addr, addrlen, &timeout); Py_END_ALLOW_THREADS if (timeout) { PyErr_SetString(socket_timeout, "timed out"); return NULL; } if (res != 0) return s->errorhandler(); Py_INCREF(Py_None); return Py_None; } Note that both the check for timeout and also the s->errorhandler() call (which defaults to set_error() and probably pre-dates timeout) use errno, everywhere. If this is wrong, I'll bring it up on python-dev. Do you have an example of a properly-coded module? For example, the first one I checked, fctlmodule.c, does it the same way. |
|||
msg47546 - (view) | Author: Tony Nelson (tony_nelson) | Date: 2006-06-18 19:37 | |
Logged In: YES user_id=1356214 Ehh, we can stop worrying. From ceval.h: "For convenience, that the value of 'errno' is restored across Py_END_ALLOW_THREADS and Py_BLOCK_THREADS." This means that I can remove from my patch the extra code to restore errno. |
|||
msg47547 - (view) | Author: Tony Nelson (tony_nelson) | Date: 2006-07-07 23:03 | |
Logged In: YES user_id=1356214 I've submitted a new patch as 1519025. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:56:09 | admin | set | github: 41443 |
2005-01-15 11:37:24 | irmen | create |