@@ -200,6 +200,7 @@ typedef struct {
200200 EventStateFlags flags ;
201201 int count ; /* Number of times this fd has triggered
202202 without being deselected. */
203+ Eterm last_select_pid ; /* Last process that called enif_select */
203204} ErtsDrvEventState ;
204205
205206struct drv_ev_state_shared {
@@ -290,6 +291,7 @@ static ERTS_INLINE int grow_drv_ev_state(ErtsSysFdType fd) {
290291 sizeof (ErtsDrvEventState ) * (new_len - old_len ));
291292 for (i = old_len ; i < new_len ; i ++ ) {
292293 drv_ev_state .v [i ].fd = (ErtsSysFdType ) i ;
294+ drv_ev_state .v [i ].last_select_pid = NIL ;
293295 }
294296 erts_atomic_set_nob (& drv_ev_state .len , new_len );
295297 for (i = 0 ; i < ERTS_CHECK_IO_DRV_EV_STATE_LOCK_CNT ; i ++ ) {
@@ -333,6 +335,8 @@ static ERTS_INLINE ErtsDrvEventState* new_drv_ev_state(ErtsDrvEventState *state,
333335 tmpl .active_events = 0 ;
334336 tmpl .type = ERTS_EV_TYPE_NONE ;
335337 tmpl .flags = 0 ;
338+ tmpl .count = 0 ;
339+ tmpl .last_select_pid = NIL ;
336340
337341 return (ErtsDrvEventState * ) safe_hash_put (& drv_ev_state .tab , (void * ) & tmpl );
338342}
@@ -922,6 +926,7 @@ deselect(ErtsDrvEventState *state, int mode)
922926 state -> type = ERTS_EV_TYPE_NONE ;
923927 state -> flags = ERTS_EV_FLAG_CLEAR ;
924928 state -> count = 0 ;
929+ state -> last_select_pid = NIL ;
925930 } else {
926931 ErtsPollEvents new_events =
927932 erts_io_control (state , ERTS_POLL_OP_MOD , state -> active_events );
@@ -1248,6 +1253,7 @@ enif_select_x(ErlNifEnv* env,
12481253 ErtsDrvSelectDataState * free_select = NULL ;
12491254 ErtsNifSelectDataState * free_nif = NULL ;
12501255 ErtsPollEvents new_events = 0 ;
1256+ const Eterm recipient = pid ? pid -> pid : env -> proc -> common .id ;
12511257#ifdef DEBUG_PRINT_MODE
12521258 char tmp_buff [255 ];
12531259#endif
@@ -1340,15 +1346,24 @@ enif_select_x(ErlNifEnv* env,
13401346 old_events = state -> events ;
13411347
13421348 if (on ) {
1349+ ASSERT (is_internal_pid (recipient ));
1350+
13431351 if (state -> type == ERTS_EV_TYPE_NONE )
13441352 ctl_op = ERTS_POLL_OP_ADD ;
13451353#if ERTS_POLL_USE_SCHEDULER_POLLING
1346- else {
1347- if (!(state -> flags & ERTS_EV_FLAG_SCHEDULER ) &&
1348- !(state -> flags & ERTS_EV_FLAG_FALLBACK ) &&
1349- (ctl_events & ERTS_POLL_EV_IN )) {
1350- if (erts_sched_poll_enabled () && (state -> flags & ERTS_EV_FLAG_NIF_SELECT ) &&
1351- state -> count ++ > 10 ) {
1354+ else if (ctl_events & ERTS_POLL_EV_IN ) {
1355+ if ((state -> flags & (ERTS_EV_FLAG_SCHEDULER |
1356+ ERTS_EV_FLAG_FALLBACK |
1357+ ERTS_EV_FLAG_NIF_SELECT )) == ERTS_EV_FLAG_NIF_SELECT
1358+ && erts_sched_poll_enabled ()) {
1359+ /* Check if this is a different process than last time.
1360+ * If so, reset the counter to prevent scheduler pollset migration
1361+ * in multi-process scenarios (e.g., multiple socket:accept callers). */
1362+ if (state -> last_select_pid != recipient ) {
1363+ state -> count = 0 ;
1364+ state -> last_select_pid = recipient ;
1365+ }
1366+ else if (++ (state -> count ) > 10 ) {
13521367 int wake_poller = 0 ;
13531368 DEBUG_PRINT_FD ("moving to scheduler ps" , state );
13541369 new_events = erts_poll_control (get_scheduler_pollset (), fd , ERTS_POLL_OP_ADD ,
@@ -1359,7 +1374,7 @@ enif_select_x(ErlNifEnv* env,
13591374 old_events = state -> events ;
13601375 }
13611376 }
1362- if ( ctl_events & ERTS_POLL_EV_IN ) {
1377+ {
13631378 ErtsSchedulerData * esdp = erts_get_scheduler_data ();
13641379 erts_io_clear_nif_select (fd , state );
13651380 /* Clear the marker in scheduler data so that the scheduler
@@ -1408,6 +1423,8 @@ enif_select_x(ErlNifEnv* env,
14081423 if (state -> type == ERTS_EV_TYPE_NIF && !old_events ) {
14091424 state -> type = ERTS_EV_TYPE_NONE ;
14101425 state -> flags = 0 ;
1426+ state -> count = 0 ;
1427+ state -> last_select_pid = NIL ;
14111428 state -> driver .nif -> in .pid = NIL ;
14121429 state -> driver .nif -> out .pid = NIL ;
14131430 state -> driver .nif -> err .pid = NIL ;
@@ -1421,8 +1438,6 @@ enif_select_x(ErlNifEnv* env,
14211438 || state -> type == ERTS_EV_TYPE_NONE );
14221439
14231440 if (on ) {
1424- const Eterm recipient = pid ? pid -> pid : env -> proc -> common .id ;
1425- ASSERT (is_internal_pid (recipient ));
14261441 if (!state -> driver .nif )
14271442 state -> driver .nif = alloc_nif_select_data ();
14281443 if (state -> type == ERTS_EV_TYPE_NONE ) {
@@ -1497,6 +1512,7 @@ enif_select_x(ErlNifEnv* env,
14971512 ret |= ERL_NIF_SELECT_STOP_SCHEDULED ;
14981513 }
14991514 state -> count = 0 ;
1515+ state -> last_select_pid = NIL ;
15001516 state -> flags &= ~ERTS_EV_FLAG_WANT_ERROR ;
15011517 }
15021518 else
@@ -1777,6 +1793,8 @@ steal_pending_stop_use(erts_dsprintf_buf_t *dsbufp, ErlDrvPort ix,
17771793 }
17781794 state -> type = ERTS_EV_TYPE_NONE ;
17791795 state -> flags = 0 ;
1796+ state -> count = 0 ;
1797+ state -> last_select_pid = NIL ;
17801798 state -> driver .stop .drv_ptr = NULL ;
17811799 }
17821800 else {
@@ -1816,6 +1834,8 @@ steal_pending_stop_nif(erts_dsprintf_buf_t *dsbufp, ErtsResource* resource,
18161834 enif_release_resource (state -> driver .stop .resource -> data );
18171835 state -> type = ERTS_EV_TYPE_NONE ;
18181836 state -> flags = 0 ;
1837+ state -> count = 0 ;
1838+ state -> last_select_pid = NIL ;
18191839 state -> driver .stop .resource = NULL ;
18201840 }
18211841 else {
@@ -2014,6 +2034,7 @@ erts_check_io(ErtsPollThread *psi, ErtsMonotonicTime timeout_time, int poll_only
20142034 erts_poll_control (get_scheduler_pollset (), fd , ERTS_POLL_OP_DEL , 0 , & wake_poller );
20152035 state -> flags &= ~(ERTS_EV_FLAG_SCHEDULER |ERTS_EV_FLAG_IN_SCHEDULER );
20162036 state -> count = 0 ;
2037+ state -> last_select_pid = NIL ;
20172038 }
20182039#endif
20192040 } else {
@@ -2034,6 +2055,7 @@ erts_check_io(ErtsPollThread *psi, ErtsMonotonicTime timeout_time, int poll_only
20342055 state -> flags &= ~(ERTS_EV_FLAG_IN_SCHEDULER |ERTS_EV_FLAG_SCHEDULER );
20352056 state -> active_events &= ~ERTS_POLL_EV_IN ;
20362057 state -> count = 0 ;
2058+ state -> last_select_pid = NIL ;
20372059 }
20382060 } else
20392061#endif
0 commit comments