9048 |
9048 |
9049 ^ super readCheck:fd |
9049 ^ super readCheck:fd |
9050 ! |
9050 ! |
9051 |
9051 |
9052 selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray |
9052 selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray |
9053 into:resultFdArray withTimeOut:millis |
9053 readableInto:readableResultFdArray writableInto:writableResultFdArray |
9054 "wait for any fd in readFdArray (an Array of integers) to become ready for |
9054 exceptionInto:exceptionResultFdArray |
9055 reading, writeFdArray to become ready for writing, or exceptFdArray to |
9055 withTimeOut:millis |
9056 arrive exceptional data (i.e. out-of-band data). |
9056 |
9057 Timeout after t milliseconds or, if the timeout time is 0, immediately.. |
9057 "wait for any fd in readFdArray (an Array of integers) to become ready for reading, |
|
9058 writeFdArray to become ready for writing, |
|
9059 or exceptFdArray to arrive exceptional data (i.e. out-of-band data). |
|
9060 Timeout after t milliseconds or - if the timeout time is 0 - immediately.. |
9058 Empty fd-sets will always wait. Zero time can be used to poll file- |
9061 Empty fd-sets will always wait. Zero time can be used to poll file- |
9059 descriptors (i.e. to check if I/O possible without blocking). |
9062 descriptors (i.e. to check if I/O possible without blocking). |
9060 The filedescriptors which are ready are returned in resultArray. |
9063 The corresponding filedescriptors which are ready are returned in readableResultFdArray, |
9061 |
9064 writableResultFdArray and exceptionResultFdArray respectively. |
9062 Return the number of selected filedescriptors" |
9065 |
|
9066 Return the (overall) number of selected filedescriptors. |
|
9067 readableResultFdArray, writableResultFdArray and exceptionResultFdArray will |
|
9068 get a nil-value stored into the slot after the last valid fileDescriptor; |
|
9069 Thus, the caller can simply scan these arrays upTo the end or a nil value." |
9063 |
9070 |
9064 %{ |
9071 %{ |
9065 fd_set rset, wset, eset; |
9072 fd_set rset, wset, eset; |
9066 struct timeval wt, et; |
9073 struct timeval wt, et; |
9067 int f, maxF, i, lX, bX; |
9074 int maxF; |
9068 INT t; |
9075 INT t; |
9069 OBJ fd, retFd; |
|
9070 int ret; |
9076 int ret; |
9071 int count, resultCount; |
9077 int cntR = 0, cntW = 0, cntE = 0; |
|
9078 int resultSizeReadable = 0, resultSizeWritable = 0, resultSizeException = 0; |
9072 int numFds = 0; |
9079 int numFds = 0; |
9073 #ifndef __isArrayLike |
9080 #ifndef __isArrayLike |
9074 # define __isArrayLike __isArray |
9081 # define __isArrayLike __isArray |
9075 #endif |
9082 #endif |
9076 |
9083 |
9077 if (!__isSmallInteger(millis)) { |
9084 if (!__isSmallInteger(millis)) { |
9078 goto fail; |
9085 goto fail; |
9079 } |
9086 } |
9080 if (! __isArrayLike(resultFdArray)) { |
9087 |
9081 goto fail; |
9088 if (readableResultFdArray != nil) { |
9082 } |
9089 if (! __isArrayLike(readableResultFdArray)) { |
9083 resultCount = __arraySize(resultFdArray); |
9090 goto fail; |
|
9091 } |
|
9092 resultSizeReadable = __arraySize(readableResultFdArray); |
|
9093 } |
|
9094 if (writableResultFdArray != nil) { |
|
9095 if (! __isArrayLike(writableResultFdArray)) { |
|
9096 goto fail; |
|
9097 } |
|
9098 resultSizeWritable = __arraySize(writableResultFdArray); |
|
9099 } |
|
9100 if (exceptionResultFdArray != nil) { |
|
9101 if (! __isArrayLike(exceptionResultFdArray)) { |
|
9102 goto fail; |
|
9103 } |
|
9104 resultSizeException = __arraySize(exceptionResultFdArray); |
|
9105 } |
9084 |
9106 |
9085 FD_ZERO(&rset); |
9107 FD_ZERO(&rset); |
9086 FD_ZERO(&wset); |
9108 FD_ZERO(&wset); |
9087 FD_ZERO(&eset); |
9109 FD_ZERO(&eset); |
9088 |
9110 |
9089 maxF = -1; |
9111 maxF = -1; |
9090 if (__isNonNilObject(readFdArray)) { |
9112 if (__isNonNilObject(readFdArray)) { |
|
9113 int i, count; |
|
9114 |
9091 if (! __isArrayLike(readFdArray)) { |
9115 if (! __isArrayLike(readFdArray)) { |
9092 goto fail; |
9116 goto fail; |
9093 } |
9117 } |
9094 count = __arraySize(readFdArray); |
9118 count = __arraySize(readFdArray); |
9095 |
9119 |
9096 for (i=0; i<count;i++) { |
9120 for (i=0; i<count;i++) { |
|
9121 OBJ fd; |
|
9122 |
9097 fd = __ArrayInstPtr(readFdArray)->a_element[i]; |
9123 fd = __ArrayInstPtr(readFdArray)->a_element[i]; |
9098 if (fd != nil) { |
9124 if (fd != nil) { |
9099 if (! __isSmallInteger(fd)) { |
9125 if (! __isSmallInteger(fd)) { |
9100 if (@global(InfoPrinting) == true) { |
9126 if (@global(InfoPrinting) == true) { |
9101 fprintf(stderr, "[OS] warning: funny read-fd (0x%x) given to select\n", fd); |
9127 fprintf(stderr, "[OS] warning: funny read-fd (0x%x) given to select\n", fd); |
9102 } |
9128 } |
9103 } else { |
9129 } else { |
|
9130 int f; |
|
9131 |
9104 f = __intVal(fd); |
9132 f = __intVal(fd); |
9105 if ((unsigned)f < FD_SETSIZE) { |
9133 if ((unsigned)f < FD_SETSIZE) { |
9106 FD_SET(f, &rset); |
9134 FD_SET(f, &rset); |
9107 if (f > maxF) maxF = f; |
9135 if (f > maxF) maxF = f; |
9108 numFds++; |
9136 numFds++; |
9206 } while (0 /* (ret < 0) && (errno == EINTR) */ ); |
9246 } while (0 /* (ret < 0) && (errno == EINTR) */ ); |
9207 } |
9247 } |
9208 __END_INTERRUPTABLE__ |
9248 __END_INTERRUPTABLE__ |
9209 |
9249 |
9210 if (ret > 0) { |
9250 if (ret > 0) { |
9211 int cnt = 0; |
9251 OBJ *__resultR = __arrayVal(readableResultFdArray); |
9212 OBJ *__result = __arrayVal(resultFdArray); |
9252 OBJ *__resultW = __arrayVal(writableResultFdArray); |
|
9253 OBJ *__resultE = __arrayVal(exceptionResultFdArray); |
|
9254 int i; |
9213 |
9255 |
9214 for (i=0; i <= maxF; i++) { |
9256 for (i=0; i <= maxF; i++) { |
9215 if (FD_ISSET(i, &rset) |
9257 if (FD_ISSET(i, &rset)) { |
9216 || FD_ISSET(i, &wset) |
9258 if (cntR < resultSizeReadable) { |
9217 || FD_ISSET(i, &eset)) { |
9259 __resultR[cntR] = __MKSMALLINT(i); |
9218 if (cnt < resultCount) { |
|
9219 __result[cnt] = __MKSMALLINT(i); |
|
9220 } |
9260 } |
9221 cnt++; |
9261 cntR++; |
|
9262 } |
|
9263 |
|
9264 if (FD_ISSET(i, &wset)) { |
|
9265 if (cntW < resultSizeWritable) { |
|
9266 __resultW[cntW] = __MKSMALLINT(i); |
|
9267 } |
|
9268 cntW++; |
|
9269 } |
|
9270 |
|
9271 if (FD_ISSET(i, &eset)) { |
|
9272 if (cntE < resultSizeException) { |
|
9273 __resultE[cntE] = __MKSMALLINT(i); |
|
9274 } |
|
9275 cntE++; |
9222 } |
9276 } |
9223 } |
9277 } |
9224 RETURN (__MKSMALLINT(cnt)); |
9278 /* add a delimiter */ |
|
9279 if (cntR < resultSizeReadable) { |
|
9280 __resultR[cntR] = nil; |
|
9281 } |
|
9282 if (cntW < resultSizeWritable) { |
|
9283 __resultW[cntW] = nil; |
|
9284 } |
|
9285 if (cntE < resultSizeException) { |
|
9286 __resultE[cntE] = nil; |
|
9287 } |
|
9288 |
|
9289 RETURN (__MKSMALLINT(cntR+cntW+cntE)); |
9225 } else { |
9290 } else { |
9226 if (ret < 0) { |
9291 if (ret < 0) { |
9227 if (errno == EINTR) { |
9292 if (errno == EINTR) { |
9228 errno = 0; |
9293 errno = 0; |
9229 @global(LastErrorNumber) = nil; |
9294 @global(LastErrorNumber) = nil; |
9253 " |
9316 " |
9254 ^ self primitiveFailed |
9317 ^ self primitiveFailed |
9255 ! |
9318 ! |
9256 |
9319 |
9257 selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray withTimeOut:millis |
9320 selectOnAnyReadable:readFdArray writable:writeFdArray exception:exceptFdArray withTimeOut:millis |
9258 "wait for any fd in readFdArray (an Array of integers) to become ready for |
9321 "wait for any fd in readFdArray (an Array of integers) to become ready for reading, |
9259 reading, writeFdArray to become ready for writing, or exceptFdArray to |
9322 writeFdArray to become ready for writing, |
9260 arrive exceptional data (i.e. out-of-band data). |
9323 or exceptFdArray to arrive exceptional data (i.e. out-of-band data). |
9261 Timeout after t milliseconds or, if the timeout time is 0, immediately.. |
9324 Timeout after t milliseconds or, if the timeout time is 0, immediately.. |
9262 Empty fd-sets will always wait. Zero time can be used to poll file- |
9325 Empty fd-sets will always wait. Zero time can be used to poll file- |
9263 descriptors (i.e. to check if I/O possible without blocking). |
9326 descriptors (i.e. to check if I/O possible without blocking). |
9264 Return first ready fd if I/O ok, nil if timed-out or interrupted." |
9327 Return the first ready fd if I/O ok, nil if timed-out or interrupted." |
9265 |
9328 |
9266 %{ |
9329 %{ |
9267 fd_set rset, wset, eset; |
9330 fd_set rset, wset, eset; |
9268 struct timeval wt, et; |
9331 struct timeval wt, et; |
9269 int f, maxF, i, lX, bX; |
9332 int f, maxF, i, lX, bX; |
9275 #ifndef __isArrayLike |
9338 #ifndef __isArrayLike |
9276 # define __isArrayLike __isArray |
9339 # define __isArrayLike __isArray |
9277 #endif |
9340 #endif |
9278 |
9341 |
9279 if (__isSmallInteger(millis)) { |
9342 if (__isSmallInteger(millis)) { |
9280 FD_ZERO(&rset); |
9343 FD_ZERO(&rset); |
9281 FD_ZERO(&wset); |
9344 FD_ZERO(&wset); |
9282 FD_ZERO(&eset); |
9345 FD_ZERO(&eset); |
9283 |
9346 |
9284 maxF = -1; |
9347 maxF = -1; |
9285 if (__isNonNilObject(readFdArray)) { |
9348 if (__isNonNilObject(readFdArray)) { |
9286 if (! __isArrayLike(readFdArray)) { |
9349 if (! __isArrayLike(readFdArray)) { |
9287 goto fail; |
9350 goto fail; |
9288 } |
9351 } |
9289 count = __arraySize(readFdArray); |
9352 count = __arraySize(readFdArray); |
9290 |
9353 |
9291 for (i=0; i<count;i++) { |
9354 for (i=0; i<count;i++) { |
9292 fd = __ArrayInstPtr(readFdArray)->a_element[i]; |
9355 fd = __ArrayInstPtr(readFdArray)->a_element[i]; |
9293 if (fd != nil) { |
9356 if (fd != nil) { |
9294 if (! __isSmallInteger(fd)) { |
9357 if (! __isSmallInteger(fd)) { |
9295 if (@global(InfoPrinting) == true) { |
9358 if (@global(InfoPrinting) == true) { |
9296 fprintf(stderr, "[OS] warning: funny read-fd (0x%x) given to select\n", fd); |
9359 fprintf(stderr, "[OS] warning: funny read-fd (0x%x) given to select\n", fd); |
9297 } |
9360 } |
9298 } else { |
9361 } else { |
9299 f = __intVal(fd); |
9362 f = __intVal(fd); |
9300 if ((unsigned)f < FD_SETSIZE) { |
9363 if ((unsigned)f < FD_SETSIZE) { |
9301 FD_SET(f, &rset); |
9364 FD_SET(f, &rset); |
9302 if (f > maxF) maxF = f; |
9365 if (f > maxF) maxF = f; |
9303 numFds++; |
9366 numFds++; |
9304 } else { |
9367 } else { |
9305 if (@global(InfoPrinting) == true) { |
9368 if (@global(InfoPrinting) == true) { |
9306 fprintf(stderr, "[OS] warning: huge read-fd (0x%x) given to select\n", fd); |
9369 fprintf(stderr, "[OS] warning: huge read-fd (0x%x) given to select\n", fd); |
9307 } |
9370 } |
9308 } |
9371 } |
9309 } |
9372 } |
9310 } |
9373 } |
9311 } |
9374 } |
9312 } |
9375 } |
9313 |
9376 |
9314 if (__isNonNilObject(writeFdArray)) { |
9377 if (__isNonNilObject(writeFdArray)) { |
9315 if (! __isArrayLike(writeFdArray)) { |
9378 if (! __isArrayLike(writeFdArray)) { |
9316 goto fail; |
9379 goto fail; |
9317 } |
9380 } |
9318 count = __arraySize(writeFdArray); |
9381 count = __arraySize(writeFdArray); |
9319 for (i=0; i<count;i++) { |
9382 for (i=0; i<count;i++) { |
9320 fd = __ArrayInstPtr(writeFdArray)->a_element[i]; |
9383 fd = __ArrayInstPtr(writeFdArray)->a_element[i]; |
9321 if (fd != nil) { |
9384 if (fd != nil) { |
9322 if (! __isSmallInteger(fd)) { |
9385 if (! __isSmallInteger(fd)) { |
9323 if (@global(InfoPrinting) == true) { |
9386 if (@global(InfoPrinting) == true) { |
9324 fprintf(stderr, "[OS] warning: funny write-fd (0x%x) given to select\n", fd); |
9387 fprintf(stderr, "[OS] warning: funny write-fd (0x%x) given to select\n", fd); |
9325 } |
9388 } |
9326 } else { |
9389 } else { |
9327 f = __intVal(fd); |
9390 f = __intVal(fd); |
9328 if ((unsigned)f < FD_SETSIZE) { |
9391 if ((unsigned)f < FD_SETSIZE) { |
9329 FD_SET(f, &wset); |
9392 FD_SET(f, &wset); |
9330 if (f > maxF) maxF = f; |
9393 if (f > maxF) maxF = f; |
9331 numFds++; |
9394 numFds++; |
9332 } else { |
9395 } else { |
9333 if (@global(InfoPrinting) == true) { |
9396 if (@global(InfoPrinting) == true) { |
9334 fprintf(stderr, "[OS] warning: huge write-fd (0x%x) given to select\n", fd); |
9397 fprintf(stderr, "[OS] warning: huge write-fd (0x%x) given to select\n", fd); |
9335 } |
9398 } |
9336 } |
9399 } |
9337 } |
9400 } |
9338 } |
9401 } |
9339 } |
9402 } |
9340 } |
9403 } |
9341 |
9404 |
9342 if (__isNonNilObject(exceptFdArray)) { |
9405 if (__isNonNilObject(exceptFdArray)) { |
9343 if (! __isArrayLike(exceptFdArray)) { |
9406 if (! __isArrayLike(exceptFdArray)) { |
9344 goto fail; |
9407 goto fail; |
9345 } |
9408 } |
9346 count = __arraySize(exceptFdArray); |
9409 count = __arraySize(exceptFdArray); |
9347 for (i=0; i<count;i++) { |
9410 for (i=0; i<count;i++) { |
9348 fd = __ArrayInstPtr(exceptFdArray)->a_element[i]; |
9411 fd = __ArrayInstPtr(exceptFdArray)->a_element[i]; |
9349 if (fd != nil) { |
9412 if (fd != nil) { |
9350 if (! __isSmallInteger(fd)) { |
9413 if (! __isSmallInteger(fd)) { |
9351 if (@global(InfoPrinting) == true) { |
9414 if (@global(InfoPrinting) == true) { |
9352 fprintf(stderr, "[OS] warning: funny except-fd (0x%x) given to select\n", fd); |
9415 fprintf(stderr, "[OS] warning: funny except-fd (0x%x) given to select\n", fd); |
9353 } |
9416 } |
9354 } else { |
9417 } else { |
9355 f = __intVal(fd); |
9418 f = __intVal(fd); |
9356 if ((unsigned)f < FD_SETSIZE) { |
9419 if ((unsigned)f < FD_SETSIZE) { |
9357 FD_SET(f, &eset); |
9420 FD_SET(f, &eset); |
9358 if (f > maxF) maxF = f; |
9421 if (f > maxF) maxF = f; |
9359 numFds++; |
9422 numFds++; |
9360 } else { |
9423 } else { |
9361 if (@global(InfoPrinting) == true) { |
9424 if (@global(InfoPrinting) == true) { |
9362 fprintf(stderr, "[OS] warning: huge except-fd (0x%x) given to select\n", fd); |
9425 fprintf(stderr, "[OS] warning: huge except-fd (0x%x) given to select\n", fd); |
9363 } |
9426 } |
9364 } |
9427 } |
9365 } |
9428 } |
9366 } |
9429 } |
9367 } |
9430 } |
9368 } |
9431 } |
9369 |
9432 |
9370 t = __intVal(millis); |
9433 t = __intVal(millis); |
9371 if (t) { |
9434 if (t) { |
9372 wt.tv_sec = t / 1000; |
9435 wt.tv_sec = t / 1000; |
9373 wt.tv_usec = (t % 1000) * 1000; |
9436 wt.tv_usec = (t % 1000) * 1000; |
9374 } else { |
9437 } else { |
9375 wt.tv_sec = wt.tv_usec = 0; |
9438 wt.tv_sec = wt.tv_usec = 0; |
9376 } |
9439 } |
9377 |
9440 |
9378 /* |
9441 /* |
9379 * make certain, that interrupt gets us out of the select |
9442 * make certain, that interrupt gets us out of the select |
9380 * However, we must then care for moved objects. |
9443 * However, we must then care for moved objects. |
9381 */ |
9444 */ |
9382 __BEGIN_INTERRUPTABLE__ |
9445 __BEGIN_INTERRUPTABLE__ |
9383 errno = 0; |
9446 errno = 0; |
9384 |
9447 |
9385 if (t == 0) { |
9448 if (t == 0) { |
9386 /* |
9449 /* |
9387 * if there is no timeout time, we can stay here interruptable. |
9450 * if there is no timeout time, we can stay here interruptable. |
9388 */ |
9451 */ |
9389 do { |
9452 do { |
9390 ret = select(maxF+1, &rset, &wset, &eset, &wt); |
9453 ret = select(maxF+1, &rset, &wset, &eset, &wt); |
9391 } while ((ret < 0) && (errno == EINTR)); |
9454 } while ((ret < 0) && (errno == EINTR)); |
9392 } else { |
9455 } else { |
9393 do { |
9456 do { |
9394 ret = select(maxF+1, &rset, &wset, &eset, &wt); |
9457 ret = select(maxF+1, &rset, &wset, &eset, &wt); |
9395 /* |
9458 /* |
9396 * for now: dont loop; if we did, we had to adjust the vt-timeval; |
9459 * for now: dont loop; if we did, we had to adjust the vt-timeval; |
9397 * could otherwise stay in this loop forever ... |
9460 * could otherwise stay in this loop forever ... |
9398 * Premature ret (before the time expired) must be handled by the caller. |
9461 * Premature ret (before the time expired) must be handled by the caller. |
9399 * A good solution is to update the wt-timeval and redo the select. |
9462 * A good solution is to update the wt-timeval and redo the select. |
9400 */ |
9463 */ |
9401 } while (0 /* (ret < 0) && (errno == EINTR) */ ); |
9464 } while (0 /* (ret < 0) && (errno == EINTR) */ ); |
9402 } |
9465 } |
9403 __END_INTERRUPTABLE__ |
9466 __END_INTERRUPTABLE__ |
9404 |
9467 |
9405 if (ret > 0) { |
9468 if (ret > 0) { |
9406 for (i=0; i <= maxF; i++) { |
9469 for (i=0; i <= maxF; i++) { |
9407 if (FD_ISSET(i, &rset) |
9470 if (FD_ISSET(i, &rset) |
9408 || FD_ISSET(i, &wset) |
9471 || FD_ISSET(i, &wset) |
9409 || FD_ISSET(i, &eset)) { |
9472 || FD_ISSET(i, &eset)) { |
9410 RETURN ( __MKSMALLINT(i) ); |
9473 RETURN ( __MKSMALLINT(i) ); |
9411 } |
9474 } |
9412 } |
9475 } |
9413 } else { |
9476 } else { |
9414 if (ret < 0) { |
9477 if (ret < 0) { |
9415 if (errno == EINTR) { |
9478 if (errno == EINTR) { |
9416 errno = 0; |
9479 errno = 0; |
9417 @global(LastErrorNumber) = nil; |
9480 @global(LastErrorNumber) = nil; |
9418 } else { |
9481 } else { |
9419 if (@global(InfoPrinting) == true) { |
9482 if (@global(InfoPrinting) == true) { |
9420 fprintf(stderr, "OS [info]: select errno = %d\n", errno); |
9483 fprintf(stderr, "OS [info]: select errno = %d\n", errno); |
9421 } |
9484 } |
9422 @global(LastErrorNumber) = __MKSMALLINT(errno); |
9485 @global(LastErrorNumber) = __MKSMALLINT(errno); |
9423 } |
9486 } |
9424 } else { |
9487 } else { |
9425 @global(LastErrorNumber) = nil; |
9488 @global(LastErrorNumber) = nil; |
9426 } |
9489 } |
9427 } |
9490 } |
9428 |
9491 |
9429 /* |
9492 /* |
9430 * Return nil (means time expired or interrupted) |
9493 * Return nil (means time expired or interrupted) |
9431 */ |
9494 */ |
9432 RETURN ( nil ); |
9495 RETURN ( nil ); |
9433 } |
9496 } |
9434 |
9497 |
9435 fail: ; |
9498 fail: ; |
9436 %}. |
9499 %}. |
9437 " |
9500 " |